<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: cosmol-studio</title>
    <description>The latest articles on DEV Community by cosmol-studio (cosmol-studio).</description>
    <link>https://dev.to/cosmol-studio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F14509%2Fa40c16d8-ff55-4723-aacb-f0bbc70bc163.png</url>
      <title>DEV Community: cosmol-studio</title>
      <link>https://dev.to/cosmol-studio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cosmol-studio"/>
    <language>en</language>
    <item>
      <title>Rust Cheminformatics Validation: From ChEMBL 37 to Billions of Exact RDKit Comparisons</title>
      <dc:creator>95028</dc:creator>
      <pubDate>Mon, 07 Sep 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/cosmol-studio/rust-cheminformatics-validation-from-chembl-37-to-billions-of-exact-rdkit-comparisons-4gol</link>
      <guid>https://dev.to/cosmol-studio/rust-cheminformatics-validation-from-chembl-37-to-billions-of-exact-rdkit-comparisons-4gol</guid>
      <description>&lt;p&gt;“Validated on millions of molecules” sounds impressive, but by itself it says surprisingly little.&lt;/p&gt;

&lt;p&gt;A cheminformatics implementation can process millions of molecules while comparing only one final output per molecule. It can also report 99.9% agreement while hiding a small but systematic semantic difference. For COSMolKit, neither is sufficient to define RDKit parity.&lt;/p&gt;

&lt;p&gt;The validation model is instead built around an explicit question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;For this declared feature boundary, which observable behaviors must match the pinned reference?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That turns validation from a molecule-count benchmark into a behavioral contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Current Validation Snapshot
&lt;/h2&gt;

&lt;p&gt;COSMolKit currently uses &lt;strong&gt;RDKit &lt;code&gt;2026.03.1&lt;/code&gt;&lt;/strong&gt; as the pinned chemistry reference for its documented parity-covered surfaces. Its largest evidence layer uses the complete ChEMBL 37 structure table: &lt;strong&gt;2,897,819 source records&lt;/strong&gt; , of which &lt;strong&gt;2,897,804 are mutually parseable&lt;/strong&gt; under the relevant sanitized comparison boundary.&lt;/p&gt;

&lt;p&gt;The current extended ChEMBL profile contains &lt;strong&gt;31 phases and 3,968 ordered shard tasks&lt;/strong&gt;. Across the consolidated accepted evidence, COSMolKit records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2,931,581,192 matching checks
0 blocking mismatches
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Distance-geometry validation additionally traverses &lt;strong&gt;2,757,910,995 individual matrix entries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The important word here is &lt;strong&gt;checks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A check may be a fingerprint vector, an atom-state field, a bond-state field, an option branch, an error outcome, a serialized state, a coordinate result, or another explicitly declared observation. Molecule count tells us how broad the input set is; comparison count tells us much more about how deep the tested boundary goes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parity Is Boundary-Scoped
&lt;/h2&gt;

&lt;p&gt;COSMolKit does not use “RDKit compatible” as a repository-wide binary label. A feature is parity-covered only for its documented boundary, and upstream APIs outside that boundary remain separate capabilities.&lt;/p&gt;

&lt;p&gt;Inside a declared boundary, however, the rule is strict. A mismatching molecule or parameter branch cannot simply be reclassified as unsupported after the result is known. Likewise, 99%, 99.9%, or any other aggregate threshold does not convert remaining mismatches into parity.&lt;/p&gt;

&lt;p&gt;The parity contract is conceptually simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;same input
same operation
same options
same output schema

COSMolKit
    vs
pinned RDKit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that comparison exposes a difference, the response must be to understand and resolve the difference, withdraw a genuinely separate capability boundary, or retain it as an executable development failure. Silently dropping the mismatching field, adding molecule-specific exclusions, or weakening the assertion is explicitly disallowed.&lt;/p&gt;

&lt;p&gt;This matters because a clean percentage can otherwise hide exactly the edge cases that compatibility testing is supposed to discover.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Corpus Layers, Three Different Jobs
&lt;/h2&gt;

&lt;p&gt;A single enormous corpus is not the entire validation strategy.&lt;/p&gt;

&lt;p&gt;COSMolKit currently uses three complementary layers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Project corpus&lt;/td&gt;
&lt;td&gt;152 records&lt;/td&gt;
&lt;td&gt;Fast daily checks and focused source-port regressions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintained strict corpus&lt;/td&gt;
&lt;td&gt;5,000 records&lt;/td&gt;
&lt;td&gt;Dense parameter matrices and detailed boundaries practical for regular testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ChEMBL 37&lt;/td&gt;
&lt;td&gt;2,897,819 source records&lt;/td&gt;
&lt;td&gt;Large-scale stress, composition, batch and concurrency auditing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These corpora are intentionally not interchangeable. The small corpus preserves highly focused regressions cheaply. The 5,000-record layer can exercise parameter combinations that may be too expensive to run exhaustively over millions of structures. ChEMBL then asks whether those implementations survive a much broader chemical distribution.&lt;/p&gt;

&lt;p&gt;The resulting model is closer to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;focused semantic cases
        +
dense option coverage
        +
large-scale stress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;than simply “use the largest dataset available.”&lt;/p&gt;

&lt;h2&gt;
  
  
  One Molecule Can Produce Hundreds of Comparisons
&lt;/h2&gt;

&lt;p&gt;SMILES writing makes the distinction especially clear.&lt;/p&gt;

&lt;p&gt;The current ChEMBL validation expands the supported writer boundary into &lt;strong&gt;768 parameter profiles&lt;/strong&gt; , combining canonical/isomeric behavior, Kekulé output, stereo cleaning, explicit bonds and hydrogens, dative handling, atom-map behavior, and rooted output choices.&lt;/p&gt;

&lt;p&gt;Across 2,854,362 eligible records, one complete matrix represents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2,192,150,016 comparisons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and that matrix was executed three times to expose instability rather than merely deterministic disagreement.&lt;/p&gt;

&lt;p&gt;So saying “2.85 million molecules passed SMILES validation” would substantially understate what was tested. The real boundary is closer to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;molecules
×
parameter branches
×
repeated execution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same principle appears elsewhere. Fingerprint validation compares full vectors and, where relevant, provenance outputs. Molecular-state tests can compare atom and bond properties rather than only a canonical string. Modern CIPLabeler validation includes full and selected assignment paths together with &lt;code&gt;_CIPCode&lt;/code&gt;, &lt;code&gt;_CIPRank&lt;/code&gt;, &lt;code&gt;_CIPNeighborOrder&lt;/code&gt;, stereo state, and exact success or failure outcomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exact Does Not Always Mean String Equality
&lt;/h2&gt;

&lt;p&gt;Different chemistry surfaces require different comparison boundaries.&lt;/p&gt;

&lt;p&gt;For discrete behavior, COSMolKit generally requires exact equality: bytes, bits, return status, atom and bond state, stereochemistry, fingerprint outputs, or deterministic error behavior.&lt;/p&gt;

&lt;p&gt;Numerical algorithms require explicit tolerances. The current project-level validation description reaches &lt;code&gt;1e-8&lt;/code&gt; for matrix entries and &lt;code&gt;1e-6&lt;/code&gt; for coordinates, energies, and gradients where those numerical surfaces are part of the covered contract. Stochastic workflows can additionally include seed handling, RNG state, random-draw behavior, and fixed-seed outcomes rather than merely asking whether a conformer “looks similar.”&lt;/p&gt;

&lt;p&gt;The principle is not “everything must be bit-identical regardless of algorithm.”&lt;/p&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Every parity surface must define what equivalence means before the result is inspected.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Validation Must Survive Composition
&lt;/h2&gt;

&lt;p&gt;Scalar correctness is necessary, but production chemistry is rarely a sequence of isolated default calls.&lt;/p&gt;

&lt;p&gt;A molecule may be parsed, sanitized, hydrogenated, edited, serialized, restored, embedded, optimized, fingerprinted, and processed through a batch pipeline. State left behind by one operation may only become observable several operations later.&lt;/p&gt;

&lt;p&gt;The ChEMBL audit therefore includes more than isolated scalar results. Current evidence exercises operation-order composition, scalar-versus-batch behavior, shared-object concurrent reads, binary roundtrips, fixed-seed conformer outcomes, and force-field paths.&lt;/p&gt;

&lt;p&gt;This connects directly to the earlier operation-contract work in COSMolKit. Internal contracts attempt to keep every molecular transition valid; differential validation then asks whether those transitions compose into the same observable behavior as the reference.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Validation Run Has an Identity
&lt;/h2&gt;

&lt;p&gt;Large validation is useful only if the result can be tied to exactly what was executed.&lt;/p&gt;

&lt;p&gt;The ChEMBL runner therefore records much more than a log saying “passed.” Its identity includes the corpus manifest, every shard checksum, phase profile, audit scripts, Git state and tracked diff, installed COSMolKit extension, Python version, NumPy environment, and pinned RDKit version. Resume is allowed only when the identity remains compatible, and individual task outputs are themselves checksummed.&lt;/p&gt;

&lt;p&gt;The ChEMBL source is deterministically partitioned into 128 shards. A run is not accepted merely because all completed jobs happened to match: missing tasks, failed tasks, a time-limited partial run, or a noninformational mismatch make the run incomplete or failing.&lt;/p&gt;

&lt;p&gt;This is particularly important for multi-million-record testing. Without an execution identity, “we once ran ChEMBL” quickly becomes difficult to distinguish from reproducible release evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Most Useful Result Was a Failure
&lt;/h2&gt;

&lt;p&gt;The strongest demonstration of the validation model is not one of the clean phases.&lt;/p&gt;

&lt;p&gt;During the retained 2026-08-20 validation execution, two new phases exposed systemic problems. Unsanitized &lt;code&gt;RemoveHs(sanitize=false)&lt;/code&gt; produced millions of mismatching state observations because surviving explicit-valence and implicit-hydrogen state differed from RDKit. Binary roundtrips preserved visible graph state and deterministic bytes while changing downstream hash and Morgan behavior after deserialization.&lt;/p&gt;

&lt;p&gt;The original report did not reinterpret these as an acceptable error rate. It explicitly recorded that the overall gate was not accepted.&lt;/p&gt;

&lt;p&gt;Both findings were subsequently traced to their underlying state semantics, corrected, retained as focused regressions, and rerun over the complete affected phase boundaries. The topology rerun now records &lt;strong&gt;45,669,848 matching observations over 2,854,376 records with zero mismatch&lt;/strong&gt; , while the binary-roundtrip rerun records &lt;strong&gt;11,534,336 matching observations over 524,288 records with zero mismatch&lt;/strong&gt;. The current &lt;code&gt;VALIDATION.md&lt;/code&gt; incorporates those accepted reruns into the consolidated zero-blocking-mismatch evidence.&lt;/p&gt;

&lt;p&gt;That episode captures the intended workflow better than any headline percentage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;large-scale audit
      ↓
systemic mismatch discovered
      ↓
source-level investigation
      ↓
implementation corrected
      ↓
focused regression retained
      ↓
complete affected boundary rerun
      ↓
evidence accepted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Validation is useful precisely because it is allowed to fail the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Billions of Comparisons Matter
&lt;/h2&gt;

&lt;p&gt;The point of billions of comparisons is not to claim that software can be proven bug-free by testing enough molecules.&lt;/p&gt;

&lt;p&gt;It cannot.&lt;/p&gt;

&lt;p&gt;Their value is that they combine several dimensions that are easy to conflate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chemical breadth
×
parameter breadth
×
state depth
×
execution modes
×
repetition
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A million molecules compared only by final SMILES provide one kind of evidence. The same molecules compared across structured molecular state, complete option matrices, fingerprints, deterministic errors, serialization, operation composition, batch paths, stochastic behavior, coordinates, energies, and matrices provide a substantially different kind.&lt;/p&gt;

&lt;p&gt;This is why COSMolKit counts comparison observations rather than presenting molecule count as the whole validation claim.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Source Semantics to Validation Evidence
&lt;/h2&gt;

&lt;p&gt;The earlier articles in this series described the other parts of the methodology.&lt;/p&gt;

&lt;p&gt;COSMolKit first separates RDKit’s mature chemistry semantics from the architecture used to carry them. Compatibility-critical behavior is reproduced from pinned upstream source rather than reconstructed by repeatedly fitting to corpus outputs. Registered operations and strict development checks then constrain how those semantics interact with the redesigned Rust molecular-state model.&lt;/p&gt;

&lt;p&gt;Validation is the final layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pinned upstream semantics
          ↓
source-backed Rust port
          ↓
operation contracts + strict CI
          ↓
focused regression matrices
          ↓
ChEMBL-scale differential audit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The corpus is therefore not asked to invent the implementation.&lt;/p&gt;

&lt;p&gt;It is asked to break it.&lt;/p&gt;

&lt;p&gt;And when it does, the mismatch remains blocking until the semantic difference is understood, corrected, preserved as a regression, and rerun over the declared boundary.&lt;/p&gt;

&lt;p&gt;That is what the current &lt;strong&gt;2.93 billion matching checks&lt;/strong&gt; are intended to represent. Not “COSMolKit tried a lot of molecules,” but a much more specific claim:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Within the explicitly documented parity-covered boundaries, the current accepted evidence reproduces pinned RDKit behavior across the recorded chemical, parameter, state, and execution surfaces with zero blocking mismatch.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the standard COSMolKit uses when it says &lt;strong&gt;RDKit parity&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  COSMolKit Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/cosmol-studio/COSMolKit" rel="noopener noreferrer"&gt;Source repository&lt;/a&gt; ·&lt;a href="https://kit.cosmol.org/" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt; ·&lt;a href="https://tools.cosmol.org/" rel="noopener noreferrer"&gt;Web tools&lt;/a&gt; ·&lt;a href="https://crates.io/crates/cosmolkit" rel="noopener noreferrer"&gt;Rust crate&lt;/a&gt; ·&lt;a href="https://pypi.org/project/cosmolkit/" rel="noopener noreferrer"&gt;Python package&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>cheminformatics</category>
      <category>testing</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Rust Cheminformatics: Porting RDKit Source Semantics to Rust</title>
      <dc:creator>95028</dc:creator>
      <pubDate>Tue, 01 Sep 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/cosmol-studio/rust-cheminformatics-porting-rdkit-source-semantics-to-rust-16je</link>
      <guid>https://dev.to/cosmol-studio/rust-cheminformatics-porting-rdkit-source-semantics-to-rust-16je</guid>
      <description>&lt;p&gt;COSMolKit currently validates its parity-covered Rust cheminformatics surfaces against pinned RDKit &lt;code&gt;2026.03.1&lt;/code&gt; using three complementary corpus tiers, culminating in the complete ChEMBL 37 structure table. The current extended profile covers &lt;strong&gt;2,897,819 source records&lt;/strong&gt; , &lt;strong&gt;31 validation phases&lt;/strong&gt; , and &lt;strong&gt;3,968 shard tasks&lt;/strong&gt;. Its consolidated accepted evidence records &lt;strong&gt;2,931,581,192 matching checks with zero blocking mismatch&lt;/strong&gt; , with distance-geometry validation additionally traversing more than &lt;strong&gt;2.75 billion matrix entries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These are not simply “molecules that produced the same final string.” Depending on the declared parity boundary, COSMolKit compares exact molecular state, fingerprints, parameter branches, serialization behavior, operation composition, batch and concurrent execution, stochastic outcomes, matrices, coordinates, energies, gradients, and errors. The exact scope is documented separately in &lt;a href="https://github.com/cosmol-studio/COSMolKit/blob/main/VALIDATION.md" rel="noopener noreferrer"&gt;&lt;code&gt;VALIDATION.md&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The more interesting question for this article is not how large the validation corpus became.&lt;/p&gt;

&lt;p&gt;It is &lt;strong&gt;how the implementation reached that result&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A straightforward way to build an RDKit-compatible Rust library is to treat RDKit as an executable oracle: implement a feature approximately, run a corpus through both implementations, inspect the mismatches, let an agent patch the failing cases, expand the corpus, and repeat. Modern coding agents make this workflow remarkably fast.&lt;/p&gt;

&lt;p&gt;COSMolKit deliberately follows a different development model.&lt;/p&gt;

&lt;p&gt;For compatibility-critical chemistry, the implementation is derived from the pinned upstream source first. Differential corpora are then used to audit that port rather than to iteratively teach a heuristic implementation how to imitate RDKit.&lt;/p&gt;

&lt;p&gt;That distinction is the subject of this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two Ways to Build an RDKit-Compatible Implementation
&lt;/h2&gt;

&lt;p&gt;With an executable reference such as RDKit, the most obvious development strategy is differential output fitting. Start with an implementation of the general algorithm, run the same molecules through RDKit and the new implementation, compare the outputs, and repair whatever differs.&lt;/p&gt;

&lt;p&gt;In the agent era, this approach is especially attractive. An agent can implement a feature from documentation or a high-level algorithm description, execute thousands of differential examples, cluster failures, infer additional rules, patch the implementation, and repeat the process with very little human intervention.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implement an approximate feature
            ↓
   run reference corpus
            ↓
   observe mismatches
            ↓
  infer missing behavior
            ↓
          patch
            ↓
      expand corpus
            ↓
         repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a legitimate engineering strategy when approximate compatibility is sufficient. It can also produce very high empirical agreement.&lt;/p&gt;

&lt;p&gt;The difficulty is that the corpus gradually becomes part of the implementation specification.&lt;/p&gt;

&lt;p&gt;A feature may reach 99% on a small corpus, only to expose an entirely new class of failures when the corpus grows. Another increase may reveal interactions between aromaticity and stereochemistry; another may expose query behavior, unusual valence state, operation ordering, or some previously unseen combination of options.&lt;/p&gt;

&lt;p&gt;The implementation therefore tends to grow together with the corpus:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;larger corpus
      ↓
new mismatch family
      ↓
new heuristic branch
      ↓
larger implementation
      ↓
larger corpus
      ↓
     ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At that point, development progress becomes difficult to estimate. “99.9% complete” does not tell us whether the remaining 0.1% consists of ten isolated cases or an entire semantic family that the implementation has not yet modeled.&lt;/p&gt;

&lt;p&gt;More importantly, even a corpus with millions of molecules cannot prove that a real production workflow will not exercise an unobserved combination.&lt;/p&gt;

&lt;p&gt;COSMolKit tries to invert this relationship.&lt;/p&gt;

&lt;h2&gt;
  
  
  Corpus Agreement and Semantic Reproduction Are Different Claims
&lt;/h2&gt;

&lt;p&gt;Consider two implementations that both report 100% agreement on the same million-molecule corpus.&lt;/p&gt;

&lt;p&gt;Implementation A was built through repeated differential correction. When the corpus exposed a mismatch, the implementation was modified until the output matched.&lt;/p&gt;

&lt;p&gt;Implementation B was constructed by tracing the relevant upstream source behavior, reproducing those state transitions in Rust, and then using the million molecules to test whether the port was correct.&lt;/p&gt;

&lt;p&gt;The headline result can be identical:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1,000,000 / 1,000,000 matched

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but the evidentiary meaning is different.&lt;/p&gt;

&lt;p&gt;The distinction is essentially this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Corpus-driven output fitting&lt;/th&gt;
&lt;th&gt;Source-backed reproduction&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reference output reveals missing behavior&lt;/td&gt;
&lt;td&gt;Upstream source defines intended behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failing example motivates implementation change&lt;/td&gt;
&lt;td&gt;First source-state divergence motivates implementation change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Corpus gradually acts as specification&lt;/td&gt;
&lt;td&gt;Corpus acts as auditor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New corpus scale may require new heuristic branches&lt;/td&gt;
&lt;td&gt;New corpus scale tests an already-defined transition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Passing observed cases supports empirical agreement&lt;/td&gt;
&lt;td&gt;Passing cases support a source-derived semantic claim&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Progress can become difficult to estimate as edge cases accumulate&lt;/td&gt;
&lt;td&gt;Remaining work can be tracked against source/call-graph closure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The first approach is not inherently illegitimate. It simply supports a different kind of confidence.&lt;/p&gt;

&lt;p&gt;For COSMolKit’s parity-covered chemistry, we wanted the second.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Corpus Should Audit the Implementation, Not Write It
&lt;/h2&gt;

&lt;p&gt;The central development rule is therefore:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Validation should verify the port. It should not become the process by which the implementation discovers what the reference probably meant.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The intended direction is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pinned upstream source
        ↓
identify source semantics
        ↓
reproduce them in Rust
        ↓
focused source regression
        ↓
large-scale differential validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;large reference corpus
        ↓
observe wrong output
        ↓
invent a correction
        ↓
      rerun
        ↓
repeat until the corpus is green
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That change in direction has consequences throughout the project.&lt;/p&gt;

&lt;p&gt;It changes how source code is written.&lt;/p&gt;

&lt;p&gt;It changes how a mismatch is debugged.&lt;/p&gt;

&lt;p&gt;It changes what an agent is allowed to do when a test fails.&lt;/p&gt;

&lt;p&gt;And it changes what “100% parity” means.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Feature Name Is Not a Specification
&lt;/h2&gt;

&lt;p&gt;Many cheminformatics features appear simple at the API level. Canonical SMILES, Morgan fingerprints, &lt;code&gt;RemoveHs&lt;/code&gt;, CIP assignment, Kekulization, ETKDG, and MMFF optimization each have understandable high-level descriptions.&lt;/p&gt;

&lt;p&gt;But mature behavior is not contained entirely in those descriptions.&lt;/p&gt;

&lt;p&gt;RDKit’s observable semantics can depend on details such as ordering conventions, helper dispatch, property-cache transitions, stereo cleanup, query handling, aromatic edge cases, implicit hydrogen state, exception timing, random-number consumption, floating-point behavior, and legacy branches.&lt;/p&gt;

&lt;p&gt;A paper can describe canonicalization.&lt;/p&gt;

&lt;p&gt;It does not necessarily describe every ordering and cleanup decision that a mature implementation makes before producing a canonical string.&lt;/p&gt;

&lt;p&gt;Documentation can describe hydrogen removal.&lt;/p&gt;

&lt;p&gt;It may not expose every state transition that later operations observe when &lt;code&gt;sanitize=false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So COSMolKit distinguishes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implements the same general feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reproduces the pinned reference semantics
within a declared boundary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second claim requires more than an API with the same name.&lt;/p&gt;

&lt;h2&gt;
  
  
  What “Line-by-Line Port” Means
&lt;/h2&gt;

&lt;p&gt;COSMolKit describes compatibility-critical work as line-by-line, source-backed porting. That phrase does not mean translating C++ syntax mechanically into Rust syntax.&lt;/p&gt;

&lt;p&gt;Rust should still be Rust.&lt;/p&gt;

&lt;p&gt;The project deliberately redesigns ownership, errors, molecular state, mutation APIs, container choices, batch execution, and other architectural layers. A C++ vector can become a more appropriate Rust set; an exception can become a typed &lt;code&gt;Result&lt;/code&gt;; mutable object behavior can be exposed through a value-style public API.&lt;/p&gt;

&lt;p&gt;What must remain traceable is the behavior.&lt;/p&gt;

&lt;p&gt;The project’s source-reproduction protocol requires relevant original source lines to be retained verbatim beside their corresponding Rust implementation as comments. Those lines become inline review anchors rather than being replaced by vague comments such as “implements RDKit behavior.”&lt;/p&gt;

&lt;p&gt;This matters even more with agent-driven development. A human or agent returning to the implementation later can see both the Rust code and the upstream logic it is supposed to reproduce without reconstructing the relationship from commit history or memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Behavior and Performance Are Tracked Separately
&lt;/h2&gt;

&lt;p&gt;A source-backed port should also be allowed to improve implementation quality.&lt;/p&gt;

&lt;p&gt;For that reason, COSMolKit’s source markers use two independent dimensions. The first records behavioral reproduction; the second records performance and algorithmic-complexity status.&lt;/p&gt;

&lt;p&gt;A behaviorally equivalent Rust implementation can therefore still be marked as slower, equivalent, unresolved, or better in implementation complexity. Conversely, a faster implementation does not gain behavioral-completion status merely because it looks elegant.&lt;/p&gt;

&lt;p&gt;This enables transformations such as replacing a linear membership structure with a more appropriate Rust container while retaining the same externally observable transition.&lt;/p&gt;

&lt;p&gt;The principle is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Compatibility should constrain semantics, not source syntax.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is what allows COSMolKit to combine a Rust-native architecture with conservative reference behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow the Source Until the Behavior Actually Lives
&lt;/h2&gt;

&lt;p&gt;Another practical problem is that mature C++ libraries rarely keep the full semantics of an operation in one function.&lt;/p&gt;

&lt;p&gt;A public function may dispatch into a helper, which calls another helper, which performs the branch that actually determines the observable result.&lt;/p&gt;

&lt;p&gt;An agent instructed only to “port function X” can easily reproduce the visible dispatcher while approximating or simplifying the deeper dependency.&lt;/p&gt;

&lt;p&gt;COSMolKit’s source protocol therefore treats the relevant upstream call graph as the real boundary. Cross-file helper functions must be followed when they contain behavior necessary to the supported operation.&lt;/p&gt;

&lt;p&gt;The question is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did we translate this entry point?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did we reproduce the source-defined behavior reached from this entry point?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That difference becomes substantial for canonicalization, stereochemistry, sanitization, conformer generation, and other deeply layered cheminformatics workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Even Language-Level Behavior May Matter
&lt;/h2&gt;

&lt;p&gt;Some reference behavior does not look like chemistry at all. It can depend on unsigned arithmetic, stream behavior, iteration order, substring handling, object lifetime, exception timing, allocation behavior, or floating-point reduction.&lt;/p&gt;

&lt;p&gt;When those details are observable inside the declared compatibility boundary, they have to be considered explicitly.&lt;/p&gt;

&lt;p&gt;The project allows three honest outcomes: reproduce the defined behavior, establish a deliberate Rust behavior where the upstream path itself is undefined, or leave the capability outside the supported boundary.&lt;/p&gt;

&lt;p&gt;The scalar InChI implementation illustrates this distinction. COSMolKit reproduces the source-defined official InChI and RDKit adapter behavior for its four documented scalar APIs, but an undefined official-C initial-allocation path becomes a deterministic structured Rust allocation error rather than an attempt to reproduce undefined memory behavior.&lt;/p&gt;

&lt;p&gt;Source-backed does not mean blindly preserving every C accident.&lt;/p&gt;

&lt;p&gt;It means being explicit about which behavior is actually being preserved.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the Large Corpus Finds a Failure
&lt;/h2&gt;

&lt;p&gt;The most important difference between the two development paradigms appears when validation finally finds a mismatch.&lt;/p&gt;

&lt;p&gt;In a corpus-fitting workflow, the mismatch itself often becomes the starting point for a fix. An agent inspects the failing molecule, finds a plausible region of the Rust implementation, makes a change, and checks whether the output now agrees.&lt;/p&gt;

&lt;p&gt;COSMolKit forbids that as sufficient justification for a source-port correction.&lt;/p&gt;

&lt;p&gt;The project’s source-bisection debugging protocol requires the mismatch to be localized to the &lt;strong&gt;first divergent state boundary&lt;/strong&gt; between upstream and Rust before the implementation is changed.&lt;/p&gt;

&lt;p&gt;Suppose a canonical SMILES differs. The final string may depend on parsing, property-cache updates, stereo preparation, ring state, canonical ranking, start-atom selection, traversal, and serialization.&lt;/p&gt;

&lt;p&gt;Instead of modifying the writer because the writer emitted the wrong string, both RDKit and Rust are instrumented at comparable checkpoints.&lt;/p&gt;

&lt;p&gt;The result might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;raw parse match
property-cache update match
stereo preparation match
double-bond stereo update DIFFER
canonical ranks DIFFER
final SMILES DIFFER

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At that point, the final string is only a symptom. The first semantic divergence occurred earlier.&lt;/p&gt;

&lt;p&gt;The correct debugging target is the double-bond stereo transition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Patch the First Divergence, Not the Last Symptom
&lt;/h2&gt;

&lt;p&gt;This gives the source-port methodology one of its most important rules:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Patch the first divergent state transition, not the final visible symptom.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A final-output patch can make one corpus case green while compensating for a different bug upstream.&lt;/p&gt;

&lt;p&gt;A first-divergence patch instead answers three questions: what was the last state where RDKit and Rust still agreed, where did they first disagree, and which upstream source block defines that transition?&lt;/p&gt;

&lt;p&gt;The source-bisection protocol explicitly rejects explanations such as “this looks likely,” “this branch seems related,” or simply “this makes the failing test pass.” A correction is expected to have a concrete upstream boundary explanation.&lt;/p&gt;

&lt;p&gt;This is particularly important for agents.&lt;/p&gt;

&lt;p&gt;Agents are very good at optimizing toward an executable objective.&lt;/p&gt;

&lt;p&gt;If the objective is merely “make this differential test pass,” they can often find a local patch rapidly.&lt;/p&gt;

&lt;p&gt;COSMolKit instead changes the objective to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Find and reproduce the missing upstream transition.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is a much harder objective to game accidentally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Large-Corpus Failures Become Small Semantic Regressions
&lt;/h2&gt;

&lt;p&gt;When a ChEMBL-scale run discovers an unusual failure, the failing molecule should not remain only as one row in a multi-million-record corpus.&lt;/p&gt;

&lt;p&gt;After the source divergence has been understood and fixed, the project retains a focused regression at the smallest stable state boundary, together with a higher-level regression when appropriate.&lt;/p&gt;

&lt;p&gt;The lifecycle is therefore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;large-corpus discovery
        ↓
source-state bisection
        ↓
first divergent source transition
        ↓
source-backed correction
        ↓
focused permanent regression
        ↓
large-corpus revalidation

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is one reason large validation does not have to produce ever-growing heuristic complexity.&lt;/p&gt;

&lt;p&gt;A new failing molecule does not become “case 17,532 that needs special handling.”&lt;/p&gt;

&lt;p&gt;It becomes evidence that some part of the source port was incomplete or incorrect.&lt;/p&gt;

&lt;p&gt;Once that transition is understood, the implementation is corrected at the semantic level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Development Progress Becomes More Predictable
&lt;/h2&gt;

&lt;p&gt;This difference also affects project planning.&lt;/p&gt;

&lt;p&gt;In a corpus-driven heuristic implementation, completion is difficult to estimate because the remaining work is partly unknown. Every larger corpus can reveal a new family of behavior that requires another local model or special case.&lt;/p&gt;

&lt;p&gt;The feature may appear almost complete for a long time while repeatedly producing new edge cases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;99.0%
99.7%
99.93%
99.98%
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The number moves toward 100%, but the amount of semantic work remaining is not necessarily proportional to the remaining percentage.&lt;/p&gt;

&lt;p&gt;A source-backed port has a different progress model. The project can inspect the upstream call graph, track which blocks are behaviorally reproduced, which remain partial, and which dependencies are still unresolved.&lt;/p&gt;

&lt;p&gt;COSMolKit’s source markers deliberately preserve that incompleteness instead of converting everything into one repository-wide “RDKit percentage.” Current feature areas therefore have different source-closure states, and the project inventory records those differences rather than pretending the entire toolkit advances as one scalar metric.&lt;/p&gt;

&lt;p&gt;That does not make source porting trivial.&lt;/p&gt;

&lt;p&gt;It makes the remaining work more legible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters in Real Applications
&lt;/h2&gt;

&lt;p&gt;A large differential corpus is extremely valuable, but production workloads are not sampled uniformly from that corpus.&lt;/p&gt;

&lt;p&gt;Real applications compose operations.&lt;/p&gt;

&lt;p&gt;A user may parse an SDF record, remove hydrogens without sanitization, modify topology, assign stereo, generate a conformer, optimize it, calculate fingerprints, serialize the result, restore it later, and run the same molecule through batch processing.&lt;/p&gt;

&lt;p&gt;A heuristic implementation may pass every isolated default-output test while failing on one of those state combinations.&lt;/p&gt;

&lt;p&gt;That is why COSMolKit’s validation includes operation-order composition, scalar-versus-batch comparisons, shared-object concurrency, serialization state, option matrices, and intermediate molecular state—not only default input/output pairs.&lt;/p&gt;

&lt;p&gt;But even this broader validation cannot enumerate every future workflow.&lt;/p&gt;

&lt;p&gt;The deeper protection comes from combining the evidence with source-defined implementation semantics.&lt;/p&gt;

&lt;p&gt;If a production input lies outside yesterday’s corpus but inside a correctly reproduced source transition, there is a reason to expect the implementation to generalize beyond the exact examples that taught nothing to the implementation in the first place.&lt;/p&gt;

&lt;p&gt;That is the important distinction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Operation Contracts Fit
&lt;/h2&gt;

&lt;p&gt;The previous article described another part of COSMolKit’s agent-era design: registered operations and strict state-transition contracts.&lt;/p&gt;

&lt;p&gt;Those contracts solve a different problem.&lt;/p&gt;

&lt;p&gt;Source reproduction asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What chemistry and state transition does RDKit actually define?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The operation system asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How is that transition allowed to interact with COSMolKit’s redesigned Rust molecule architecture?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An upstream function may define a specific hydrogen-removal transition. The source port reproduces that logic. COSMolKit’s operation system then ensures that the Rust implementation declares the topology edit, mutation authority, mapping, and derived-state obligations required to carry that transition safely through its own value/COW architecture.&lt;/p&gt;

&lt;p&gt;So the complete development path is not just source porting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream semantics
        ↓
source-backed Rust implementation
        ↓
operation contract
        ↓
strict development checks
        ↓
focused regression
        ↓
large-scale parity validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each layer catches a different class of failure.&lt;/p&gt;

&lt;p&gt;Source reproduction protects against inventing the wrong chemistry. Operation contracts protect against dropping state obligations while adapting that chemistry to a different architecture. Strict mode makes many of those obligations executable during agent development. Validation then tests whether the complete observable boundary actually agrees with the reference.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the ChEMBL Numbers Mean
&lt;/h2&gt;

&lt;p&gt;This brings us back to the numbers at the beginning.&lt;/p&gt;

&lt;p&gt;The current COSMolKit ChEMBL 37 record is not meant to say merely:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We tried 2.9 million molecules and they all looked good.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The stronger claim is narrower and more precise:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For the explicitly documented parity-covered surfaces, a source-backed implementation was subjected to the declared exact or numerical comparison boundary over the recorded corpus and option profiles, and the accepted validation currently contains zero blocking mismatch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The distinction matters.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;2,897,804 molecules&lt;/code&gt; describes corpus breadth.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;2,931,581,192 matching checks&lt;/code&gt; describes far more of the observable comparison surface.&lt;/p&gt;

&lt;p&gt;The source-reproduction protocol describes where the implementation semantics came from.&lt;/p&gt;

&lt;p&gt;The source-bisection protocol describes what happens when the validation finds a difference.&lt;/p&gt;

&lt;p&gt;The operation system describes how those semantics are transferred safely into COSMolKit’s redesigned molecular-state architecture.&lt;/p&gt;

&lt;p&gt;None of these numbers or mechanisms is sufficient alone.&lt;/p&gt;

&lt;p&gt;Together, they form the evidence chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Fast Agent Coding to Controlled Scientific Porting
&lt;/h2&gt;

&lt;p&gt;Coding agents make a previously impractical class of work possible. A small team can now inspect, port, test, and debug enormous mature scientific codebases at a speed that would have been unrealistic only a few years ago.&lt;/p&gt;

&lt;p&gt;But the easiest way to use that speed is not necessarily the safest.&lt;/p&gt;

&lt;p&gt;If an agent repeatedly learns from final output mismatches, implementation speed can simply accelerate the accumulation of heuristic branches. Corpus size grows, the implementation keeps chasing it, and the remaining development effort becomes difficult to predict. Even extremely high observed agreement cannot guarantee that an unseen production composition does not exercise a rule the implementation never actually understood.&lt;/p&gt;

&lt;p&gt;COSMolKit tries to use agents differently.&lt;/p&gt;

&lt;p&gt;The agent is not asked to infer RDKit from outputs. It is asked to read the pinned source, preserve the source correspondence, reproduce the relevant transition, pass through explicit operation contracts, and use differential validation as an auditor. When a mismatch appears, the job is not to make the example green; it is to locate the first semantic divergence and finish the port.&lt;/p&gt;

&lt;p&gt;That changes the role of the corpus from teacher to examiner.&lt;/p&gt;

&lt;p&gt;And it changes the role of the agent from heuristic optimizer to source-constrained implementer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: The Result and the Method Are the Same Story
&lt;/h2&gt;

&lt;p&gt;The current validation results are intentionally large: the complete ChEMBL 37 source, millions of molecular records, billions of compared states and outputs, option matrices, operation composition, batch execution, concurrency, serialization, stochastic paths, force fields, fingerprints, and state-sensitive chemistry. Within their explicitly documented covered boundaries, the current accepted evidence records zero blocking mismatch against pinned RDKit &lt;code&gt;2026.03.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But the point of this article is that &lt;strong&gt;the scale of the benchmark is not the core differentiator&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A large corpus can tell us that two implementations agree on a large corpus.&lt;/p&gt;

&lt;p&gt;It cannot, by itself, tell us why.&lt;/p&gt;

&lt;p&gt;COSMolKit’s answer is to connect the output evidence back to the implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pinned upstream source
        ↓
traceable source reproduction
        ↓
Rust-native architectural adaptation
        ↓
operation contracts + strict checks
        ↓
first-divergence debugging
        ↓
focused regressions
        ↓
large-scale validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why we do not treat 99% or 99.9% agreement as an almost-finished version of parity inside a covered boundary. A remaining mismatch is evidence that some semantic transition is still unexplained.&lt;/p&gt;

&lt;p&gt;And it is why reaching 100% is not supposed to require an endless sequence of corpus-specific patches.&lt;/p&gt;

&lt;p&gt;The goal is not to teach a Rust implementation to imitate RDKit’s outputs.&lt;/p&gt;

&lt;p&gt;It is to &lt;strong&gt;port the semantics that produce those outputs, then use the largest practical validation surface to prove that the port survived contact with reality.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is the distinction COSMolKit is trying to make in Rust cheminformatics.&lt;/p&gt;

&lt;h2&gt;
  
  
  COSMolKit Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/cosmol-studio/COSMolKit" rel="noopener noreferrer"&gt;Source repository&lt;/a&gt; ·&lt;a href="https://kit.cosmol.org/" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt; ·&lt;a href="https://tools.cosmol.org/" rel="noopener noreferrer"&gt;Web tools&lt;/a&gt; ·&lt;a href="https://crates.io/crates/cosmolkit" rel="noopener noreferrer"&gt;Rust crate&lt;/a&gt; ·&lt;a href="https://pypi.org/project/cosmolkit/" rel="noopener noreferrer"&gt;Python package&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>cheminformatics</category>
      <category>opensource</category>
      <category>testing</category>
    </item>
    <item>
      <title>Rust Cheminformatics State Management and Molecular Mutation</title>
      <dc:creator>95028</dc:creator>
      <pubDate>Fri, 28 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/cosmol-studio/rust-cheminformatics-state-management-and-molecular-mutation-n6</link>
      <guid>https://dev.to/cosmol-studio/rust-cheminformatics-state-management-and-molecular-mutation-n6</guid>
      <description>&lt;p&gt;AI agents have changed the economics of software porting.&lt;/p&gt;

&lt;p&gt;A translation task that once required days of manual work can now be pushed forward at remarkable speed. Large call chains can be traced, C++ functions can be translated into Rust, tests can be generated, and mismatches can be investigated in parallel.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Rust cheminformatics&lt;/strong&gt; , this is exciting.&lt;/p&gt;

&lt;p&gt;It is also dangerous.&lt;/p&gt;

&lt;p&gt;The hardest part of porting a mature chemistry library is often not translating the visible algorithm. It is preserving the decades of implicit state semantics surrounding that algorithm.&lt;/p&gt;

&lt;p&gt;RDKit has been exercised by real users, real datasets, and real combinations of operations for many years. Its state-management model is not always what we would design from scratch today, but its behavior has been shaped by enormous practical exposure.&lt;/p&gt;

&lt;p&gt;An AI agent porting one function into Rust does not inherit that history automatically.&lt;/p&gt;

&lt;p&gt;It may reproduce the visible control flow perfectly and still miss something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this operation changes atom identity
this property must be remapped
this cache survives
this one must be cleared
this error path leaves partial state
this stereochemical state is still observable
this non-sanitizing branch preserves explicit valence

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That leads to one of the central engineering problems in COSMolKit:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do we scale agent-driven source porting without scaling hidden molecular-state bugs at the same rate?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Our answer is not to assume that the agent will always remember every lifecycle rule.&lt;/p&gt;

&lt;p&gt;Instead, we try to move as many of those obligations as possible into executable architecture.&lt;/p&gt;

&lt;p&gt;That is the purpose of the COSMolKit operation system.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottleneck Has Moved
&lt;/h2&gt;

&lt;p&gt;Before modern coding agents, porting a mature cheminformatics routine was expensive largely because writing the code itself was expensive.&lt;/p&gt;

&lt;p&gt;A human developer would spend substantial time reading the source, translating data structures, rewriting control flow, compiling, debugging, and adding tests.&lt;/p&gt;

&lt;p&gt;That slowness had an accidental benefit: the developer often accumulated a large mental model of the surrounding implementation while working.&lt;/p&gt;

&lt;p&gt;The situation is different now.&lt;/p&gt;

&lt;p&gt;An agent can process source much faster than a human can deeply review every state transition.&lt;/p&gt;

&lt;p&gt;The bottleneck moves from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can we write the port?

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can we trust the port to preserve every hidden state obligation?

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That distinction matters enormously for cheminformatics.&lt;/p&gt;

&lt;p&gt;A molecular operation rarely changes only the thing named in its API.&lt;/p&gt;

&lt;p&gt;Consider hydrogen removal.&lt;/p&gt;

&lt;p&gt;At first glance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RemoveHs
=
find hydrogen atoms
+
delete them

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But deleting explicit hydrogen atoms changes the molecular topology.&lt;/p&gt;

&lt;p&gt;That can affect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;atom indices
bond indices
coordinates
atom-indexed properties
bond-indexed properties
stereo references
explicit valence
implicit hydrogen state
rings
aromaticity
computed chemistry state
cached representations

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An agent can translate the hydrogen-removal loop correctly and still get the resulting molecule wrong.&lt;/p&gt;

&lt;p&gt;This is the difference between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source control flow copied correctly

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;molecule lifecycle copied correctly

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first is a local code problem.&lt;/p&gt;

&lt;p&gt;The second is a system problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mature Libraries Contain More Semantics Than Their APIs Reveal
&lt;/h2&gt;

&lt;p&gt;RDKit is a mature C++ codebase.&lt;/p&gt;

&lt;p&gt;Some of its behavior is explicit in algorithmic code. Some of it is encoded through object state, property caches, ordering conventions, mutation timing, helper functions, legacy compatibility, and the sequencing of multiple internal operations.&lt;/p&gt;

&lt;p&gt;That accumulated behavior has survived years of production use.&lt;/p&gt;

&lt;p&gt;A new Rust implementation does not get the same guarantee merely because its code looks cleaner.&lt;/p&gt;

&lt;p&gt;In fact, a cleaner-looking rewrite can be wrong precisely because it simplifies behavior that turned out to matter.&lt;/p&gt;

&lt;p&gt;For example, an agent might reason:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;topology changed
→ valence cache is stale
→ invalidate valence

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That sounds reasonable.&lt;/p&gt;

&lt;p&gt;But if the reference implementation intentionally updates property state before the topology edit and preserves specific resulting values afterward, then generic invalidation is not equivalent behavior.&lt;/p&gt;

&lt;p&gt;The problem is subtle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A molecular state transition can be correct only relative to the semantics of the operation being reproduced.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is no universal rule saying that every topology edit should clear every derived value.&lt;/p&gt;

&lt;p&gt;There is also no safe universal rule saying that apparently unaffected state should be preserved.&lt;/p&gt;

&lt;p&gt;The correct transition depends on the source-defined behavior.&lt;/p&gt;

&lt;p&gt;This is why source-backed porting and state-management contracts have to work together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Speed Magnifies Hidden-State Risk
&lt;/h2&gt;

&lt;p&gt;Agents are particularly good at translating explicit structure.&lt;/p&gt;

&lt;p&gt;They can usually handle transformations such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;
&lt;span class="n"&gt;pointer&lt;/span&gt; &lt;span class="n"&gt;traversal&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;indexed&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;reference&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt;
&lt;span class="n"&gt;exception&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;Rust&lt;/span&gt; &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;iterator&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;integer&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;typed&lt;/span&gt; &lt;span class="n"&gt;Rust&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are visible in the source.&lt;/p&gt;

&lt;p&gt;The more dangerous obligations often live one level above the visible implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;after this edit, coordinates must follow a new atom mapping

ring state is still valid only under a particular structural condition

stereo state must be recomputed because ligand identity changed

this operation is allowed to modify topology but not properties

this source error occurs after some mutation has already happened

this cache is semantic state, while that cache is only a performance optimization

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are easy to lose when the unit of work is “port this function.”&lt;/p&gt;

&lt;p&gt;A prompt such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please consider all dependent molecular state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;is not a sufficient architecture.&lt;/p&gt;

&lt;p&gt;The better approach is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make dependent-state obligations explicit enough that the implementation cannot quietly ignore them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the direction of COSMolKit’s operation system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do Not Make Correctness Depend on the Agent Remembering Everything
&lt;/h2&gt;

&lt;p&gt;The goal of the operation framework is not to make agents infallible.&lt;/p&gt;

&lt;p&gt;It is to reduce the number of correctness properties that depend on trusting the agent.&lt;/p&gt;

&lt;p&gt;Public mutation-capable molecule operations are registered through the COSMolKit operation system.&lt;/p&gt;

&lt;p&gt;Each operation specification describes more than its function name.&lt;/p&gt;

&lt;p&gt;The current registry model includes fields such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;method
implementation function
domain
operation kind
topology edit
block access
mutation surface
automatic remapping
derived-state effects
semantic preconditions
mapping requirements
support policy
parity policy
I/O roundtrip metadata
invariant profile

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact machinery will continue to evolve, but the architectural idea is stable:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before an operation is implemented, its authority and obligations should be declared.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That changes the review model.&lt;/p&gt;

&lt;p&gt;Instead of asking a reviewer to infer from hundreds of lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What does this operation think it is allowed to mutate?

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the registry should answer directly.&lt;/p&gt;

&lt;p&gt;And instead of trusting that the implementation remembered all affected derived state, the operation contract should describe what must happen to it.&lt;/p&gt;

&lt;p&gt;The registry is therefore not just metadata.&lt;/p&gt;

&lt;p&gt;In strict builds, important parts of it have execution owners and runtime checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mutation Authority Is a Capability
&lt;/h2&gt;

&lt;p&gt;One of the most important registry concepts is &lt;code&gt;access&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For each molecular block that an operation may touch, access is classified as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;none
read
write

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the authoritative block capability.&lt;/p&gt;

&lt;p&gt;If an operation is declared read-only for coordinates, its implementation should not suddenly mutate coordinates because doing so was convenient.&lt;/p&gt;

&lt;p&gt;If it has no access to properties, property mutation is a contract violation.&lt;/p&gt;

&lt;p&gt;If the operation actually needs more authority, the correct fix is not to bypass the framework.&lt;/p&gt;

&lt;p&gt;The contract must be updated and reviewed.&lt;/p&gt;

&lt;p&gt;This creates a useful separation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chemistry code:
what transition should happen?

operation contract:
what state may this operation touch?

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is especially valuable in an agent-driven codebase.&lt;/p&gt;

&lt;p&gt;An agent can make an implementation mistake.&lt;/p&gt;

&lt;p&gt;But a mistake that crosses a declared capability boundary can be detected structurally rather than waiting for a chemically visible failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;OpParts&lt;/code&gt;: The Agent Does Not Receive the Whole Mutable Molecule
&lt;/h2&gt;

&lt;p&gt;COSMolKit operation bodies do not receive unrestricted mutable access to all molecule internals.&lt;/p&gt;

&lt;p&gt;They operate through an internal capability object called &lt;code&gt;OpParts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;OpParts&lt;/code&gt; is responsible for infrastructure such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cheap working-value creation
copy-on-write block detachment
registry-derived access capabilities
mutation permission checks
topology mapping
registered remapping
cache transition tracing
derived-effect tracking
operation finalization

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is deliberately not responsible for chemistry.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;OpParts&lt;/code&gt; should not decide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;which hydrogens are removable
how aromaticity is perceived
how CIP ranking works
how a ring algorithm behaves
how sanitization should proceed

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those rules belong to source-backed chemistry implementations.&lt;/p&gt;

&lt;p&gt;The separation can be viewed as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                Pinned Source
                     |
                     | defines chemistry
                     v
             Operation Body
                     |
                     | requests state changes
                     v
                 OpParts
          +----------+----------+
          |          |          |
       access     mapping    derived state
          |          |          |
          +----------+----------+
                     v
                  finish()
                     |
                     v
                 strict CI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The chemistry implementation says what should happen.&lt;/p&gt;

&lt;p&gt;The operation framework controls how that transition is allowed to touch shared molecular state.&lt;/p&gt;

&lt;p&gt;This distinction is one of the main safeguards against agent-generated architectural drift.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rust Privacy Is Part of the Guardrail
&lt;/h2&gt;

&lt;p&gt;A design rule is much stronger when violating it requires fighting the language.&lt;/p&gt;

&lt;p&gt;COSMolKit therefore keeps the internal working &lt;code&gt;Molecule&lt;/code&gt; inside the private operation runtime.&lt;/p&gt;

&lt;p&gt;Operation bodies are expected to receive &lt;code&gt;&amp;amp;mut OpParts&lt;/code&gt;, not raw mutable molecule internals.&lt;/p&gt;

&lt;p&gt;Helpers called by operation bodies should consume narrowed representations such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MoleculeReadParts
atom slices
bond slices
coordinate blocks
typed assignment plans
typed update plans

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rather than using a raw whole-molecule escape hatch.&lt;/p&gt;

&lt;p&gt;That boundary exists for a reason.&lt;/p&gt;

&lt;p&gt;If every operation body could simply obtain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;Molecule&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then the registry would describe one architecture while the implementation quietly used another.&lt;/p&gt;

&lt;p&gt;For agent-generated code, such escape paths are especially dangerous because they provide the easiest local solution.&lt;/p&gt;

&lt;p&gt;An agent trying to make a test pass will naturally prefer the shortest path available.&lt;/p&gt;

&lt;p&gt;The architecture should make the shortest path the correct one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write-Owned State Should Have One Timeline
&lt;/h2&gt;

&lt;p&gt;Another subtle rule prevents stale-state bugs inside one operation.&lt;/p&gt;

&lt;p&gt;Suppose topology is write-owned.&lt;/p&gt;

&lt;p&gt;A dangerous implementation shape would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;read old topology
      |
      +---------------+
      |               |
mutate working        |
topology              |
      |               |
      v               |
continue reading &amp;lt;----+
old topology
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the same operation is reasoning from two different molecular timelines.&lt;/p&gt;

&lt;p&gt;COSMolKit instead expects reads and writes of a write-owned block to come from the same local owned working value.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;begin topology
      |
      +-- inspect
      +-- calculate
      +-- mutate
      +-- return/commit

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fallible mutation APIs are scoped so the current owned block returns to the working molecule on both success and error.&lt;/p&gt;

&lt;p&gt;This matters because agent-generated code frequently uses &lt;code&gt;?&lt;/code&gt; aggressively.&lt;/p&gt;

&lt;p&gt;Without a structured mutation scope, it is easy for an early return to leave state in an unexpected intermediate representation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strong and Weak Topology Operations
&lt;/h2&gt;

&lt;p&gt;One of the most useful distinctions in the operation system is between strong topology edits and weak topology-state edits.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;strong topology operation&lt;/strong&gt; changes one or more of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;atom count
bond count
atom ordering
bond ordering
atom identity mapping
bond identity mapping

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Examples include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;add atom
remove atom
add bond
remove bond
add/remove hydrogens
renumber atoms
fragment
combine

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These operations potentially change the index space used by other molecular state.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;weak topology-state operation&lt;/strong&gt; keeps atom and bond identities stable but modifies graph state.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kekulize
sanitize
set aromaticity
change formal charge
change bond order
assign stereo from existing topology or coordinates

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Weak does not mean harmless.&lt;/p&gt;

&lt;p&gt;A weak operation can still invalidate valence, aromaticity, stereo, drawing state, or other derived information.&lt;/p&gt;

&lt;p&gt;But it does not require the same identity migration as deleting or renumbering atoms.&lt;/p&gt;

&lt;p&gt;This classification gives the system more information than:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"the molecule changed"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And again, this is useful specifically in an agent-driven environment.&lt;/p&gt;

&lt;p&gt;An agent should not have to rediscover from scratch whether an operation needs topology remapping.&lt;/p&gt;

&lt;p&gt;That fact should be part of the registered operation contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Topology Mapping Must Be Explicit
&lt;/h2&gt;

&lt;p&gt;Consider removing atom 4 from a six-atom molecule.&lt;/p&gt;

&lt;p&gt;Before the edit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;atom 0 → coordinate row 0
atom 1 → coordinate row 1
atom 2 → coordinate row 2
atom 3 → coordinate row 3
atom 4 → coordinate row 4
atom 5 → coordinate row 5

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After compaction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new atom 4
=
old atom 5

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If coordinates are not remapped, the molecule may still be perfectly memory-safe.&lt;/p&gt;

&lt;p&gt;The coordinate array may even still have the correct number of rows.&lt;/p&gt;

&lt;p&gt;But the chemistry is wrong.&lt;/p&gt;

&lt;p&gt;The same problem applies to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;atom property lists
bond property lists
stereo references
substance groups
drawing annotations
index-sensitive derived state

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For strong operations, topology mapping is therefore treated as a first-class artifact where required.&lt;/p&gt;

&lt;p&gt;Dependent state must be handled explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;remap
recompute
invalidate
drop a separately unsupported capability
or fail

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leaving stale indices behind is not a valid result.&lt;/p&gt;

&lt;p&gt;Rust’s borrow checker cannot detect this category of bug.&lt;/p&gt;

&lt;p&gt;The operation contract can at least force the implementation to acknowledge that the problem exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Block Access and Derived-State Effects Are Different Questions
&lt;/h2&gt;

&lt;p&gt;A particularly important design decision in the current operation system is that state access and derived-state obligations are separate axes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;access&lt;/code&gt; answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What may this operation read or write?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;derived_effects&lt;/code&gt; answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What must happen to affected derived chemistry state?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These are deliberately not interchangeable.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;access:
    read → topology, derived cache
    write → properties

derived effects:
    recompute → aromaticity
    preserve → rings
    invalidate → drawing

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Declaring that ring state should be preserved does not automatically give an operation permission to read or write every cache entry.&lt;/p&gt;

&lt;p&gt;Likewise, declaring recomputation does not itself grant unrelated block access.&lt;/p&gt;

&lt;p&gt;This separation makes the contract harder to accidentally overinterpret.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four Derived-State Outcomes
&lt;/h2&gt;

&lt;p&gt;The current molecule operation model classifies affected derived state into four pairwise-disjoint categories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;recompute
preserve
invalidate
operation_defined

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Recompute
&lt;/h3&gt;

&lt;p&gt;The operation must produce fresh framework-visible state, or explicitly clear it when the reproduced source behavior leaves no materialized replacement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Invalidate
&lt;/h3&gt;

&lt;p&gt;The existing value is stale and must be cleared.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preserve
&lt;/h3&gt;

&lt;p&gt;The previous value remains valid.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operation-defined
&lt;/h3&gt;

&lt;p&gt;The source requires a state transition that cannot be truthfully described by the other three categories.&lt;/p&gt;

&lt;p&gt;This final category is intentionally narrow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preservation Should Require Evidence
&lt;/h2&gt;

&lt;p&gt;Imagine an agent ports hydrogen addition.&lt;/p&gt;

&lt;p&gt;It reasons:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adding terminal H atoms cannot create a ring
therefore preserve ring state

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That may be correct.&lt;/p&gt;

&lt;p&gt;But in a large codebase, “probably still valid” is not a strong enough state-management policy.&lt;/p&gt;

&lt;p&gt;COSMolKit’s strict operation system can require an approved preservation proof.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;PreservationProof&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;LeafAtomAppend&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can validate structural conditions such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;old atom identities preserved
old bond identities preserved
new atoms only appended
new atoms are degree-one leaves

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;before ring information is accepted as preserved.&lt;/p&gt;

&lt;p&gt;So the sequence becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent:
"rings remain valid"

framework:
"show the structural condition that makes that true"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is precisely the kind of responsibility that should not depend only on an agent’s local reasoning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why an Escape Hatch Is Still Necessary
&lt;/h2&gt;

&lt;p&gt;A contract system becomes dangerous if it forces real source semantics into an oversimplified model.&lt;/p&gt;

&lt;p&gt;Sometimes the upstream implementation performs a state transition that cannot honestly be described as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;preserve
recompute
invalidate

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;COSMolKit therefore keeps &lt;code&gt;operation_defined&lt;/code&gt; as a narrowly controlled escape hatch.&lt;/p&gt;

&lt;p&gt;It delegates the transition mechanism.&lt;/p&gt;

&lt;p&gt;It does &lt;strong&gt;not&lt;/strong&gt; waive the correctness obligation.&lt;/p&gt;

&lt;p&gt;The current contract permits exactly one use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;valence
in the hydrogen-removal operation family

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The registry macro rejects other uses, strict runtime validation repeats that allow-list, and registry tests lock the current decision.&lt;/p&gt;

&lt;p&gt;This is a good example of an important project principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The architecture must constrain the port, but it must not rewrite source semantics merely to make the architecture prettier.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If RDKit defines an awkward but observable transition, the Rust design should model it honestly.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;RemoveHs(sanitize=false)&lt;/code&gt;: A Real Agent-Era Failure Mode
&lt;/h2&gt;

&lt;p&gt;Hydrogen removal is an excellent example of why this system exists.&lt;/p&gt;

&lt;p&gt;A superficially reasonable agent implementation could look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;identify removable H atoms
delete atoms
delete bonds
remap coordinates
invalidate valence
return

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That implementation might even be architecturally clean.&lt;/p&gt;

&lt;p&gt;It can still be semantically wrong.&lt;/p&gt;

&lt;p&gt;The current validated COSMolKit boundary for &lt;code&gt;RemoveHs(sanitize=false)&lt;/code&gt; includes RDKit’s non-strict property-cache update before removal and the surviving explicit-valence and implicit-hydrogen fields afterward.&lt;/p&gt;

&lt;p&gt;Those states have to be migrated through the declared topology mapping rather than generically erased.&lt;/p&gt;

&lt;p&gt;The current ChEMBL 37 topology-operation phase exercises both value-style and in-place &lt;code&gt;RemoveHs(sanitize=false)&lt;/code&gt; branches.&lt;/p&gt;

&lt;p&gt;Its accepted result covers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2,854,376 records
45,669,848 exact matches
0 blocking mismatches

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;against pinned RDKit &lt;code&gt;2026.03.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The lesson is larger than hydrogen removal.&lt;/p&gt;

&lt;p&gt;An agent can produce something that is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;locally reasonable
memory-safe
cleanly written
well tested on simple examples

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and still miss source-defined molecular state semantics.&lt;/p&gt;

&lt;p&gt;That is exactly the category of mistake the operation system is trying to make harder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strict Mode Turns Architecture Into an Executable Guardrail
&lt;/h2&gt;

&lt;p&gt;A design document is useful.&lt;/p&gt;

&lt;p&gt;A failing build is stronger.&lt;/p&gt;

&lt;p&gt;COSMolKit’s development and CI mode enables strict operation contracts and runtime invariants.&lt;/p&gt;

&lt;p&gt;The current development rules require:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo check &lt;span class="nt"&gt;-p&lt;/span&gt; cosmolkit-core &lt;span class="nt"&gt;--features&lt;/span&gt; op-contracts-strict
cargo &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; cosmolkit-core &lt;span class="nt"&gt;--release&lt;/span&gt; &lt;span class="nt"&gt;--features&lt;/span&gt; op-contracts-strict

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;op-contracts-strict&lt;/code&gt; enables both operation-contract checks and molecule runtime invariants in development/CI.&lt;/p&gt;

&lt;p&gt;That turns several architectural expectations into executable failures.&lt;/p&gt;

&lt;p&gt;Examples include conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mutate an undeclared block
→ strict failure

perform a strong topology edit
without required mapping
→ strict failure

declare preserved derived state
without an approved proof
→ strict failure

declare invalidation
but never clear the affected state
→ strict failure

write derived cache state
without matching effect authority
→ strict failure

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The precise enforcement varies by contract field, and the repository explicitly documents which fields are currently runtime-enforced, generated as evidence matrices, or still require operation-specific tests.&lt;/p&gt;

&lt;p&gt;That honesty is important.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;io_roundtrip&lt;/code&gt; is currently registry metadata and operation-specific testing responsibility rather than a universal field-driven runtime runner, while &lt;code&gt;invariant_profile&lt;/code&gt; is represented in generated matrices but does not yet select truly distinct profile-specific execution.&lt;/p&gt;

&lt;p&gt;A contract system should not claim enforcement it does not actually have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strict Mode Is Especially Valuable for Agent-Generated Code
&lt;/h2&gt;

&lt;p&gt;A human developer reading the operation-system design might remember:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;don't access working Molecule directly
don't mix independent read and write views
record strong topology edits
return checked-out blocks on errors
clear invalidated state

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An agent may remember all of that too.&lt;/p&gt;

&lt;p&gt;But it may also forget one rule during a large refactor.&lt;/p&gt;

&lt;p&gt;The point of strict mode is to make forgetting less survivable.&lt;/p&gt;

&lt;p&gt;This changes the development model from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prompt says:
"please respect architecture"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;architecture says:
"violate this and CI should fail"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a much better match for high-throughput agent development.&lt;/p&gt;

&lt;p&gt;Agents are extremely useful when the feedback loop is strong.&lt;/p&gt;

&lt;p&gt;They are much more dangerous when correctness depends on invisible conventions.&lt;/p&gt;

&lt;p&gt;The operation system tries to convert conventions into feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Goal Is Not to Trust the Agent More
&lt;/h2&gt;

&lt;p&gt;This distinction is worth stating clearly.&lt;/p&gt;

&lt;p&gt;COSMolKit’s operation system is not based on the idea that agents can be made trustworthy through better prompts.&lt;/p&gt;

&lt;p&gt;Its purpose is closer to the opposite:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make fewer correctness properties depend on trusting the agent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent can still write the wrong chemistry.&lt;/p&gt;

&lt;p&gt;It can still misunderstand an upstream branch.&lt;/p&gt;

&lt;p&gt;It can still port a helper incorrectly.&lt;/p&gt;

&lt;p&gt;Operation contracts cannot prove that CIP ranking is chemically correct or that a ring-perception algorithm matches RDKit.&lt;/p&gt;

&lt;p&gt;They solve another layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Did this operation stay inside its declared mutation surface?

Did it produce the required topology mapping?

Did it handle affected derived state?

Did it leave the molecule structurally coherent?

Did its error path respect the operation lifecycle?

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That distinction gives COSMolKit a layered correctness model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four Different Correctness Layers
&lt;/h2&gt;

&lt;p&gt;The current architecture can be understood as four separate questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Source reproduction
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Did we identify and reproduce the intended upstream state transition?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is handled by the source-reproduction discipline.&lt;/p&gt;

&lt;p&gt;Relevant C/C++ source is retained beside the Rust implementation as review anchors, and behavioral reproduction is tracked explicitly.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Operation contracts
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Did the implementation touch only the state it declared, and did it declare the necessary migration obligations?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the operation registry and &lt;code&gt;OpParts&lt;/code&gt; layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Strict execution
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Did the implementation actually fulfill those obligations during development and CI?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is where contract traces, preservation proofs, access checks, mappings, and invariants become executable guardrails.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Differential validation
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Does the resulting supported observable behavior match the pinned RDKit reference?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the parity layer.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;             RDKit Source
                 |
                 v
         Source-Backed Port
                 |
                 v
          Operation Contract
          +------+-------+
          |      |      |
       access  mapping  effects
          |      |      |
          +------+-------+
                 v
              strict
                 |
                 v
        RDKit parity validation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No single layer replaces the others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contracts Do Not Prove Chemistry
&lt;/h2&gt;

&lt;p&gt;This is an important limitation.&lt;/p&gt;

&lt;p&gt;A completely contract-valid operation can still implement the wrong chemical rule.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;topology mapping correct
cache invalidation correct
all permissions respected
molecule structurally valid

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wrong aromaticity assignment

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The operation system would not magically know.&lt;/p&gt;

&lt;p&gt;That is why COSMolKit continues to require source-backed behavior and parity validation for supported RDKit-compatible surfaces.&lt;/p&gt;

&lt;p&gt;The current project explicitly separates invariant tests from parity tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;invariants:
is the COSMolKit state internally valid?

parity:
does the supported behavior match RDKit?

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A molecule may pass all invariants and still fail parity.&lt;/p&gt;

&lt;p&gt;This separation is critical.&lt;/p&gt;

&lt;p&gt;Otherwise, a sophisticated architecture could create false confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Enemy Is Composition
&lt;/h2&gt;

&lt;p&gt;Many molecular bugs do not appear when an operation is tested alone.&lt;/p&gt;

&lt;p&gt;They appear after composition.&lt;/p&gt;

&lt;p&gt;Consider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;parse
 ↓
sanitize
 ↓
remove hydrogens
 ↓
add hydrogens
 ↓
assign stereochemistry
 ↓
generate coordinates
 ↓
calculate fingerprint

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each individual function may produce a plausible result.&lt;/p&gt;

&lt;p&gt;The failure may occur only because operation 3 left behind state that operation 6 later trusted.&lt;/p&gt;

&lt;p&gt;This category of bug is particularly hard for a fast-moving agent port.&lt;/p&gt;

&lt;p&gt;Single-function tests encourage local reasoning.&lt;/p&gt;

&lt;p&gt;Production workflows exercise state transitions across long chains.&lt;/p&gt;

&lt;p&gt;A mature library like RDKit has accumulated years of exposure to such combinations.&lt;/p&gt;

&lt;p&gt;A new implementation cannot wait decades to discover every interaction through users.&lt;/p&gt;

&lt;p&gt;Operation contracts are an attempt to move some of that integration discipline earlier.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;operation A leaves whatever state it happens to leave

operation B assumes whatever state it happens to receive

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the desired model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;operation A
    ↓
must finish at a declared contract boundary
    ↓
operation B
    ↓
receives a state with explicit lifecycle semantics

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does not eliminate composition bugs.&lt;/p&gt;

&lt;p&gt;But it reduces the amount of undocumented state that can leak from one operation into another.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manufacturing Some of the Discipline That Time Normally Provides
&lt;/h2&gt;

&lt;p&gt;Mature scientific libraries acquire robustness through multiple forces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;careful developers
large user bases
edge-case bug reports
production workflows
years of accidental stress testing

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A new Rust toolkit does not have all of that history.&lt;/p&gt;

&lt;p&gt;Agent development makes this more extreme because implementation breadth can grow much faster than production exposure.&lt;/p&gt;

&lt;p&gt;That creates an imbalance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;code surface
grows quickly

real-world validation history
grows slowly

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The operation system is one attempt to close part of that gap.&lt;/p&gt;

&lt;p&gt;Not by pretending that contracts replace production experience.&lt;/p&gt;

&lt;p&gt;They do not.&lt;/p&gt;

&lt;p&gt;But by converting certain classes of integration assumption into explicit, testable structure before users discover them.&lt;/p&gt;

&lt;p&gt;A useful way to think about it is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Operation contracts try to manufacture some of the integration discipline that mature libraries normally acquire only after years of production use.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is particularly valuable when implementation throughput is agent-amplified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Release Builds Should Not Pay the Full Contract Cost
&lt;/h2&gt;

&lt;p&gt;Strict architectural verification is useful in development.&lt;/p&gt;

&lt;p&gt;Production chemistry should not necessarily pay for all of it.&lt;/p&gt;

&lt;p&gt;COSMolKit therefore separates ordinary operation execution from contract-only checking.&lt;/p&gt;

&lt;p&gt;Strict development and CI builds can include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source snapshots needed for contracts
permission assertions
mutation traces
preservation proofs
mapping checks
full invariant scans
finish-time validation

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The optimized release build still follows the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public wrapper
operation implementation
OpParts mutation route
copy-on-write/in-place path
topology migration
derived-state updates

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but omits development-only checking where the contract permits it.&lt;/p&gt;

&lt;p&gt;The important rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Release optimization must not switch to a different chemistry algorithm.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Otherwise the project would validate one implementation and ship another.&lt;/p&gt;

&lt;p&gt;Strict mode is therefore a development guardrail, not an alternate chemistry engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Development Makes Fail-Closed Behavior More Important
&lt;/h2&gt;

&lt;p&gt;There is another related principle.&lt;/p&gt;

&lt;p&gt;When an agent encounters an unimplemented source branch, there is a temptation to return something plausible and move forward.&lt;/p&gt;

&lt;p&gt;In scientific software, that can be worse than an explicit failure.&lt;/p&gt;

&lt;p&gt;A chemically meaningful-looking result may propagate through a long pipeline before anyone notices it was produced by a fallback.&lt;/p&gt;

&lt;p&gt;COSMolKit therefore prefers explicit unsupported errors at separately documented capability boundaries rather than:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;silent fallback
best-effort approximation
placeholder chemistry

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the distinction must remain strict:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;separately unsupported capability
≠
failing row inside a claimed parity boundary

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once a capability is claimed as parity-covered, individual mismatches cannot be carved out after the fact and renamed unsupported.&lt;/p&gt;

&lt;p&gt;This is another place where architecture helps contain the tendency of high-throughput development to optimize for immediate green tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Source Porting and Operation Contracts Solve Different Problems
&lt;/h2&gt;

&lt;p&gt;It is tempting to think that a line-by-line source port makes the operation system unnecessary.&lt;/p&gt;

&lt;p&gt;It does not.&lt;/p&gt;

&lt;p&gt;Source porting answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What did the upstream implementation do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The operation system answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How is that behavior allowed to interact with COSMolKit’s redesigned molecular state model?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Remember that COSMolKit deliberately does not clone RDKit’s entire object architecture.&lt;/p&gt;

&lt;p&gt;It uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;value-style APIs
explicit in-place mutation
copy-on-write storage
typed state
registered operation boundaries
Rust ownership

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So even when the source chemistry is reproduced correctly, the surrounding state lifecycle must be adapted to the new architecture.&lt;/p&gt;

&lt;p&gt;That adaptation is exactly where semantic mistakes can appear.&lt;/p&gt;

&lt;p&gt;Therefore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;backed&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;
&lt;span class="n"&gt;without&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;contracts&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;chemistry&lt;/span&gt; &lt;span class="n"&gt;may&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;correct&lt;/span&gt; &lt;span class="n"&gt;locally&lt;/span&gt;
  &lt;span class="n"&gt;but&lt;/span&gt; &lt;span class="n"&gt;migration&lt;/span&gt; &lt;span class="n"&gt;may&lt;/span&gt; &lt;span class="n"&gt;drift&lt;/span&gt;

&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;contracts&lt;/span&gt;
&lt;span class="n"&gt;without&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;backed&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;may&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;coherent&lt;/span&gt;
  &lt;span class="n"&gt;but&lt;/span&gt; &lt;span class="n"&gt;chemistry&lt;/span&gt; &lt;span class="n"&gt;may&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;wrong&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two disciplines are complementary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Large-Scale Validation Is the Final Layer, Not the First Design Tool
&lt;/h2&gt;

&lt;p&gt;COSMolKit then validates these implementations against pinned RDKit behavior.&lt;/p&gt;

&lt;p&gt;The current ChEMBL 37 validation uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2,897,819 source records
2,897,804 mutually parseable records
31 configured phases
3,968 shard tasks

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The consolidated evidence currently records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2,931,581,192 matching checks
0 blocking mismatches

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with distance-geometry validation additionally traversing billions of matrix entries.&lt;/p&gt;

&lt;p&gt;The important point is not merely the size.&lt;/p&gt;

&lt;p&gt;It is the direction of causality.&lt;/p&gt;

&lt;p&gt;The intended workflow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream source
     ↓
source-backed Rust implementation
     ↓
operation-contract enforcement
     ↓
focused regression tests
     ↓
large-scale validation

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;large corpus
     ↓
observe mismatch
     ↓
invent local patch
     ↓
rerun
     ↓
repeat until green

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The corpus verifies the implementation.&lt;/p&gt;

&lt;p&gt;It should not become the algorithm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Throughput Without Semantic Throughput Is Dangerous
&lt;/h2&gt;

&lt;p&gt;AI agents make it possible to move faster than previous scientific software projects.&lt;/p&gt;

&lt;p&gt;But implementation throughput is not the same as semantic throughput.&lt;/p&gt;

&lt;p&gt;You can add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;more functions
more APIs
more branches
more file formats
more fingerprint families

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;faster than you can truly understand the interactions between them.&lt;/p&gt;

&lt;p&gt;Without architectural constraints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent speed
→ implementation surface grows
→ hidden semantic assumptions grow
→ composition risk grows
→ semantic debt grows

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The desired alternative is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent speed
      +
source-backed porting
      +
operation contracts
      +
strict CI
      +
large parity validation
      ↓
implementation throughput can grow
without semantic debt growing at the same rate

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That does not make large-scale agent development automatically safe.&lt;/p&gt;

&lt;p&gt;It makes safety a first-class engineering problem rather than an assumption.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Different Role for Architecture in the Agent Era
&lt;/h2&gt;

&lt;p&gt;Traditional software architecture is often discussed in terms of maintainability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clean abstractions
modularity
separation of concerns

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those still matter.&lt;/p&gt;

&lt;p&gt;But agent-driven development adds another purpose:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Architecture becomes a constraint system for code generation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A useful architecture does not merely make correct code elegant.&lt;/p&gt;

&lt;p&gt;It makes incorrect shortcuts difficult.&lt;/p&gt;

&lt;p&gt;For COSMolKit, that means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;no unrestricted mutable molecule in operation bodies

no undeclared mutation authority

no strong topology edit without explicit migration semantics

no silent cache preservation without evidence

no easy unsupported fallback inside a claimed boundary

no contract-sensitive development signoff without strict mode

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a different way to think about software design.&lt;/p&gt;

&lt;p&gt;The architecture is not only for humans who read the code later.&lt;/p&gt;

&lt;p&gt;It is also part of the feedback environment in which agents write the code now.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Goal Is Fewer Trust Assumptions
&lt;/h2&gt;

&lt;p&gt;AI agents are extraordinarily useful for source analysis, translation, testing, debugging, and large-scale engineering.&lt;/p&gt;

&lt;p&gt;COSMolKit uses that capability aggressively.&lt;/p&gt;

&lt;p&gt;But the correct response to faster code generation is not weaker engineering discipline.&lt;/p&gt;

&lt;p&gt;It is stronger executable discipline.&lt;/p&gt;

&lt;p&gt;For a mature domain such as cheminformatics, the difficult knowledge is already distributed across:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream source
state transitions
error behavior
operation ordering
cache semantics
real-world edge cases

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An agent can help reproduce that knowledge.&lt;/p&gt;

&lt;p&gt;It should not be expected to hold all of it implicitly at once.&lt;/p&gt;

&lt;p&gt;So the goal of the COSMolKit operation system is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Make the agent trustworthy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Make fewer correctness properties depend on trusting the agent.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Source-backed ports define the intended chemistry.&lt;/p&gt;

&lt;p&gt;Operation contracts define mutation authority and state obligations.&lt;/p&gt;

&lt;p&gt;Strict execution turns those rules into development-time failures.&lt;/p&gt;

&lt;p&gt;Parity validation checks whether the observable result still matches the reference.&lt;/p&gt;

&lt;p&gt;Together, these layers provide a path toward something that matters increasingly in the agent era:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;high-throughput scientific software development without treating semantic correctness as an afterthought.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For Rust cheminformatics, that may be one of the most important architectural problems to solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  COSMolKit Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/cosmol-studio/COSMolKit" rel="noopener noreferrer"&gt;Source repository&lt;/a&gt; ·&lt;a href="https://kit.cosmol.org/" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt; ·&lt;a href="https://tools.cosmol.org/" rel="noopener noreferrer"&gt;Web tools&lt;/a&gt; ·&lt;a href="https://crates.io/crates/cosmolkit" rel="noopener noreferrer"&gt;Rust crate&lt;/a&gt; ·&lt;a href="https://pypi.org/project/cosmolkit/" rel="noopener noreferrer"&gt;Python package&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>cheminformatics</category>
      <category>ai</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Rust Cheminformatics Beyond RDKit Bindings: Redesigning Molecular APIs for Rust</title>
      <dc:creator>95028</dc:creator>
      <pubDate>Sun, 23 Aug 2026 01:00:00 +0000</pubDate>
      <link>https://dev.to/cosmol-studio/rust-cheminformatics-beyond-rdkit-bindings-redesigning-molecular-apis-for-rust-55gc</link>
      <guid>https://dev.to/cosmol-studio/rust-cheminformatics-beyond-rdkit-bindings-redesigning-molecular-apis-for-rust-55gc</guid>
      <description>&lt;p&gt;Most discussions about &lt;strong&gt;Rust cheminformatics&lt;/strong&gt; begin with the same question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do we bring RDKit functionality into Rust?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The obvious answers are bindings, FFI, or a direct API clone. All three are useful approaches.&lt;/p&gt;

&lt;p&gt;When we started building &lt;a href="https://github.com/cosmol-studio/COSMolKit" rel="noopener noreferrer"&gt;COSMolKit&lt;/a&gt;, however, we became interested in a different question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the chemistry must remain compatible with RDKit, does the software architecture have to remain compatible with RDKit too?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Our answer is no.&lt;/p&gt;

&lt;p&gt;RDKit contains more than two decades of accumulated cheminformatics knowledge: edge cases, ordering rules, stereochemical behavior, file-format semantics, cache transitions, error paths, and production experience that would be extremely difficult to rediscover independently.&lt;/p&gt;

&lt;p&gt;That is exactly the part worth preserving.&lt;/p&gt;

&lt;p&gt;But preserving chemistry semantics does not require reproducing every ownership pattern, mutation convention, cache lifetime, or object-model decision inherited from a mature C++ codebase.&lt;/p&gt;

&lt;p&gt;That distinction became the foundation of COSMolKit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;preserve difficult-to-rediscover chemistry semantics
                         ↓
                redesign ownership
                         ↓
               make mutation explicit
                         ↓
          control molecular state transitions
                         ↓
             scale naturally to batches

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal is not “RDKit with Rust syntax.”&lt;/p&gt;

&lt;p&gt;It is to ask what a modern molecular toolkit can look like if reference chemistry and software architecture are treated as separate design problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Molecular Software Has Two Correctness Problems
&lt;/h2&gt;

&lt;p&gt;A cheminformatics toolkit has at least two different responsibilities.&lt;/p&gt;

&lt;p&gt;The first is &lt;strong&gt;chemical correctness&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is aromaticity correct?&lt;/li&gt;
&lt;li&gt;Is stereochemistry correct?&lt;/li&gt;
&lt;li&gt;Does canonicalization match?&lt;/li&gt;
&lt;li&gt;Are fingerprints correct?&lt;/li&gt;
&lt;li&gt;Does hydrogen handling reproduce the reference?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second is &lt;strong&gt;software-state correctness&lt;/strong&gt; :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did this operation mutate the source unexpectedly?&lt;/li&gt;
&lt;li&gt;Are coordinates still aligned with atom indices?&lt;/li&gt;
&lt;li&gt;Is cached ring information still valid?&lt;/li&gt;
&lt;li&gt;Did stereo state survive a topology edit correctly?&lt;/li&gt;
&lt;li&gt;Does a failed operation leave a coherent molecule?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These problems are related, but they are not the same.&lt;/p&gt;

&lt;p&gt;A molecule can be perfectly memory-safe and still contain stale chemistry state.&lt;/p&gt;

&lt;p&gt;It can have a coordinate matrix with exactly the right dimensions whose rows now correspond to the wrong atoms.&lt;/p&gt;

&lt;p&gt;It can have valid bond indices while retaining stereochemistry derived from an earlier topology.&lt;/p&gt;

&lt;p&gt;Rust helps enormously with the first layer of software safety: ownership, lifetimes, aliasing, and memory safety.&lt;/p&gt;

&lt;p&gt;But Rust’s borrow checker cannot answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this cached molecular state still semantically valid after this chemical operation?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That requires a higher-level model.&lt;/p&gt;

&lt;p&gt;This distinction drives much of COSMolKit’s architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chemical correctness
        ↓
source-backed reference semantics

software-state correctness
        ↓
value semantics
explicit mutation
controlled state transitions
mapping and invalidation

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Rust Cheminformatics Should Not Hide Mutation
&lt;/h2&gt;

&lt;p&gt;Molecules look deceptively simple as objects.&lt;/p&gt;

&lt;p&gt;A molecule has atoms and bonds. Add hydrogens. Remove hydrogens. Kekulize it. Generate coordinates. Sanitize it.&lt;/p&gt;

&lt;p&gt;But each of those operations can affect much more than its name suggests.&lt;/p&gt;

&lt;p&gt;Removing an atom may affect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;atom and bond indices,&lt;/li&gt;
&lt;li&gt;coordinates,&lt;/li&gt;
&lt;li&gt;atom- and bond-indexed properties,&lt;/li&gt;
&lt;li&gt;stereochemistry,&lt;/li&gt;
&lt;li&gt;ring state,&lt;/li&gt;
&lt;li&gt;valence state,&lt;/li&gt;
&lt;li&gt;aromaticity state,&lt;/li&gt;
&lt;li&gt;adjacency,&lt;/li&gt;
&lt;li&gt;and downstream computed representations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes hidden mutation particularly dangerous in cheminformatics.&lt;/p&gt;

&lt;p&gt;COSMolKit therefore makes the default molecular workflow value-oriented:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;mol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Molecule&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_smiles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CCO"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;mol_h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mol&lt;/span&gt;&lt;span class="nf"&gt;.with_hydrogens&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;mol_2d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mol_h&lt;/span&gt;&lt;span class="nf"&gt;.with_2d_coordinates&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mol
 │
 ├── with_hydrogens() ──────&amp;gt; mol_h
 │
 └── remains unchanged

mol_h
 │
 └── with_2d_coordinates() ─&amp;gt; mol_2d

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A transformation produces another molecular value.&lt;/p&gt;

&lt;p&gt;The source remains observable as the value it represented before the transformation.&lt;/p&gt;

&lt;p&gt;This makes scientific workflows easier to reason about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;raw
 ↓
sanitized
 ↓
hydrogenated
 ↓
embedded
 ↓
optimized

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each stage has an explicit identity.&lt;/p&gt;

&lt;p&gt;Intermediate states can be inspected, compared, cached, branched, or reused without asking which earlier object may have been silently modified.&lt;/p&gt;

&lt;p&gt;The public promise is &lt;strong&gt;value semantics&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The implementation is free to optimize how those values share physical storage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Value Semantics Do Not Require Deep Copies
&lt;/h2&gt;

&lt;p&gt;A naïve value-oriented molecule API could be prohibitively expensive.&lt;/p&gt;

&lt;p&gt;A molecule may contain topology, coordinates, conformers, properties, and derived state. Deep-copying all of that for every transformation would turn a cleaner interface into a performance penalty.&lt;/p&gt;

&lt;p&gt;COSMolKit therefore separates semantic identity from storage identity.&lt;/p&gt;

&lt;p&gt;Large pieces of molecular state can be shared internally and detached only when an operation actually needs to write them.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Molecule A
 ├── topology ───────┐
 ├── coordinates ────┼──── shared
 └── properties ─────┘

        with_hydrogens()

Molecule B
 ├── topology' ← changed
 ├── coordinates' ← remapped when necessary
 └── properties ───── shared if unchanged

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important distinction is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public contract:
    molecule values do not visibly alias

implementation strategy:
    unchanged storage may be shared

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy-on-write is therefore an optimization, not a public semantic promise.&lt;/p&gt;

&lt;p&gt;Users should not need to know whether an internal &lt;code&gt;Arc&lt;/code&gt; detached during an operation.&lt;/p&gt;

&lt;p&gt;They should be able to rely on something simpler:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Transforming one molecular value must not unexpectedly alter another one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is one place where Rust’s ownership model is more than an implementation detail. It provides a natural foundation for separating what a molecular value means from where its bytes happen to live.&lt;/p&gt;

&lt;h2&gt;
  
  
  In-Place Mutation Still Matters
&lt;/h2&gt;

&lt;p&gt;Value semantics are a strong default, but there are workloads where preserving an old molecular value is unnecessary.&lt;/p&gt;

&lt;p&gt;Rust cheminformatics also needs an efficient mutation path.&lt;/p&gt;

&lt;p&gt;COSMolKit uses one deliberately simple rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every public in-place &lt;code&gt;Molecule&lt;/code&gt; operation ends in &lt;code&gt;_&lt;/code&gt;, and &lt;code&gt;_&lt;/code&gt; has no other public &lt;code&gt;Molecule&lt;/code&gt; meaning.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mol&lt;/span&gt;&lt;span class="nf"&gt;.with_hydrogens&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;versus:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;mol&lt;/span&gt;&lt;span class="nf"&gt;.add_hydrogens_&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The convention extends naturally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;mol&lt;/span&gt;&lt;span class="nf"&gt;.remove_hydrogens_&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;mol&lt;/span&gt;&lt;span class="nf"&gt;.kekulize_&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;mol&lt;/span&gt;&lt;span class="nf"&gt;.sanitize_&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;mol&lt;/span&gt;&lt;span class="nf"&gt;.compute_2d_coordinates_&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is deliberately boring.&lt;/p&gt;

&lt;p&gt;That is the point.&lt;/p&gt;

&lt;p&gt;A reader should be able to identify mutation from the call site without remembering operation-specific conventions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;value style

mol2 = mol.with_hydrogens()

source preserved
new value returned

in-place style

mol.add_hydrogens_()

receiver may change
mutation obvious at call site

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two interfaces are not intended to become separate chemistry implementations.&lt;/p&gt;

&lt;p&gt;They pass through the same operation machinery and chemistry logic.&lt;/p&gt;

&lt;p&gt;The difference is ownership behavior.&lt;/p&gt;

&lt;p&gt;A value-style operation preserves the source and detaches writable state when necessary.&lt;/p&gt;

&lt;p&gt;An in-place operation can mutate uniquely owned storage directly.&lt;/p&gt;

&lt;p&gt;So:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Choosing the in-place API changes ownership behavior, not the intended chemistry semantics.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The error contract is explicit as well. In-place operations are not generally transactional. If the underlying algorithm fails after partial mutation, the molecule remains internally complete, but it is not necessarily restored to its previous value.&lt;/p&gt;

&lt;p&gt;When failure-preserving behavior matters, the value-style interface is the appropriate choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hard Problem Is Everything Mutation Invalidates
&lt;/h2&gt;

&lt;p&gt;The real difficulty begins once a molecular operation changes state.&lt;/p&gt;

&lt;p&gt;A conventional implementation can easily accumulate rules like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;remove atom
→ rebuild adjacency

change bond
→ clear rings

remove H
→ update valence somewhere

renumber atoms
→ remember coordinates

change coordinates
→ maybe update stereo

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every individual rule may be reasonable.&lt;/p&gt;

&lt;p&gt;The problem is that molecular-state management becomes distributed across dozens of functions.&lt;/p&gt;

&lt;p&gt;Eventually correctness depends on every operation remembering every consequence.&lt;/p&gt;

&lt;p&gt;COSMolKit instead routes public mutation-capable operations through a registered operation system.&lt;/p&gt;

&lt;p&gt;At a high level, an operation declares things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what state it may access,&lt;/li&gt;
&lt;li&gt;what state it may mutate,&lt;/li&gt;
&lt;li&gt;what kind of topology edit it performs,&lt;/li&gt;
&lt;li&gt;what dependent data requires migration,&lt;/li&gt;
&lt;li&gt;what derived state is affected,&lt;/li&gt;
&lt;li&gt;what support/parity boundary applies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This changes the architecture from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;operation implementation
    decides chemistry
    decides mutation authority
    decides mapping
    decides invalidation
    decides preservation

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;toward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;operation contract
    declares authority and obligations

operation body
    implements chemistry

operation framework
    controls state transition

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference matters because chemistry implementations should answer chemical questions.&lt;/p&gt;

&lt;p&gt;They should not individually reinvent the lifecycle rules for the entire molecule.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Memory Safety to Molecular-State Safety
&lt;/h2&gt;

&lt;p&gt;This is the easiest way to understand the operation system.&lt;/p&gt;

&lt;p&gt;Rust already asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Who is allowed to mutate this memory?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;COSMolKit adds another question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which molecular operation is allowed to mutate this class of chemical state?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That higher-level capability is represented internally through the operation system and its &lt;code&gt;OpParts&lt;/code&gt; execution boundary.&lt;/p&gt;

&lt;p&gt;Operation bodies do not simply receive unrestricted mutable access to the entire molecule.&lt;/p&gt;

&lt;p&gt;Instead, they work through state capabilities derived from the registered operation.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          Operation Contract
                 |
                 v
              OpParts
         +-------+--------+
         |       |        |
     topology coordinates properties
         |       |        |
         +---- controlled +
                 |
                 v
          chemistry logic
                 |
                 v
              result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The chemistry implementation still decides how hydrogen handling, stereochemistry, ring perception, or sanitization behaves.&lt;/p&gt;

&lt;p&gt;The framework decides which state that implementation is allowed to touch and how the surrounding molecular value must be migrated.&lt;/p&gt;

&lt;p&gt;Rust protects memory safety.&lt;/p&gt;

&lt;p&gt;The operation system is intended to protect molecular-state safety.&lt;/p&gt;

&lt;h2&gt;
  
  
  Topology Changes Need Explicit Consequences
&lt;/h2&gt;

&lt;p&gt;Not every molecular operation changes topology in the same way.&lt;/p&gt;

&lt;p&gt;Some operations change atom or bond identity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;add/remove atoms,&lt;/li&gt;
&lt;li&gt;add/remove bonds,&lt;/li&gt;
&lt;li&gt;add/remove explicit hydrogens,&lt;/li&gt;
&lt;li&gt;renumber,&lt;/li&gt;
&lt;li&gt;fragment,&lt;/li&gt;
&lt;li&gt;combine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Others keep atom and bond identity stable while changing graph state:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;kekulize,&lt;/li&gt;
&lt;li&gt;sanitize,&lt;/li&gt;
&lt;li&gt;change bond order,&lt;/li&gt;
&lt;li&gt;change formal charge,&lt;/li&gt;
&lt;li&gt;assign aromaticity,&lt;/li&gt;
&lt;li&gt;assign stereochemistry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The distinction matters because identity-changing operations can invalidate the index space used by other data.&lt;/p&gt;

&lt;p&gt;Consider coordinates.&lt;/p&gt;

&lt;p&gt;Before removing an atom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;atom 0 → coordinate row 0
atom 1 → coordinate row 1
atom 2 → coordinate row 2
atom 3 → coordinate row 3
atom 4 → coordinate row 4
atom 5 → coordinate row 5

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove atom 4, compact the table, and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new atom 4 = old atom 5

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The coordinate row must follow the same mapping.&lt;/p&gt;

&lt;p&gt;The same problem applies to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;atom properties,&lt;/li&gt;
&lt;li&gt;bond properties,&lt;/li&gt;
&lt;li&gt;stereochemical references,&lt;/li&gt;
&lt;li&gt;SDF property lists,&lt;/li&gt;
&lt;li&gt;structural annotations,&lt;/li&gt;
&lt;li&gt;and any other index-sensitive state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After an identity-changing topology operation, dependent state must be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;remapped
recomputed
invalidated
explicitly dropped when outside support
or rejected

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;“Leave it there” is not a valid option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Derived State Needs More Than &lt;code&gt;clear_cache()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A simple molecular-state strategy would invalidate everything after every topology edit.&lt;/p&gt;

&lt;p&gt;That is safe in some cases, inefficient in others, and sometimes semantically wrong relative to the reference behavior.&lt;/p&gt;

&lt;p&gt;The opposite strategy—preserve everything that appears unaffected—is more dangerous.&lt;/p&gt;

&lt;p&gt;COSMolKit therefore models different derived-state outcomes explicitly.&lt;/p&gt;

&lt;p&gt;At the conceptual level, an affected state may be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;recomputed
preserved
invalidated

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and rare source-defined transitions may require more specialized treatment.&lt;/p&gt;

&lt;p&gt;One detail is especially important: preservation should not be a casual annotation.&lt;/p&gt;

&lt;p&gt;Suppose adding explicit hydrogens should preserve previously computed ring information.&lt;/p&gt;

&lt;p&gt;An implementation could simply declare:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rings remain valid

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But a stronger design asks why.&lt;/p&gt;

&lt;p&gt;For example, if the topology change can be structurally established as only appending degree-one leaf atoms while preserving the old graph identity, then keeping the old ring state can be justified by a concrete preservation condition.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;operation:
"rings remain valid"

framework:
"under what structural condition?"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a much stronger model than scattering &lt;code&gt;clear_cache()&lt;/code&gt; calls throughout chemistry code.&lt;/p&gt;

&lt;p&gt;The detailed derived-state permission model deserves its own article; the key point here is that state transitions become part of the operation contract instead of invisible local convention.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development Contracts Without the Runtime Tax
&lt;/h2&gt;

&lt;p&gt;At this point an obvious objection appears:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Doesn’t all of this checking make every molecular operation expensive?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It would, if the complete development contract were always part of production execution.&lt;/p&gt;

&lt;p&gt;COSMolKit separates the chemistry/state-transition path from development-only verification.&lt;/p&gt;

&lt;p&gt;In strict development and CI builds, the operation framework can check things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mutation authority,&lt;/li&gt;
&lt;li&gt;mapping obligations,&lt;/li&gt;
&lt;li&gt;derived-state transitions,&lt;/li&gt;
&lt;li&gt;preservation conditions,&lt;/li&gt;
&lt;li&gt;molecule invariants,&lt;/li&gt;
&lt;li&gt;operation finalization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The default optimized release build follows the same chemistry implementation and the same state-migration path, but omits contract-only tracing and assertions where appropriate.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;development / CI

chemistry
   +
state migration
   +
contract verification
   +
invariant checking

release

chemistry
   +
same state migration

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Optimization mode must not select a different chemistry or state-transition algorithm.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Otherwise the project would validate one implementation and ship another.&lt;/p&gt;

&lt;p&gt;The contract system is a development guardrail, not a second chemistry engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redesign Does Not Mean Reinterpreting Chemistry
&lt;/h2&gt;

&lt;p&gt;All of this architectural freedom raises the obvious question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If COSMolKit redesigns ownership, mutation, and molecular state, how do we know it has not quietly changed the chemistry?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is where we draw a hard boundary between architecture and semantics.&lt;/p&gt;

&lt;p&gt;For compatibility-sensitive behavior, COSMolKit uses source-backed reproduction against pinned upstream implementations.&lt;/p&gt;

&lt;p&gt;Relevant upstream logic is retained alongside corresponding Rust code as review anchors, and compatibility claims are attached to explicit behavioral boundaries rather than inferred from API similarity.&lt;/p&gt;

&lt;p&gt;The architecture may change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C++ object mutation
        ↓
Rust value-style operation

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source container
        ↓
different Rust data structure

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but the declared observable semantics must remain compatible.&lt;/p&gt;

&lt;p&gt;This leads to one of the core principles of the project:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Compatibility should constrain observable semantics, not prevent architectural improvement.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And this is not only a design intention.&lt;/p&gt;

&lt;p&gt;For surfaces declared parity-covered, COSMolKit validates against pinned RDKit &lt;code&gt;2026.03.1&lt;/code&gt; over explicit comparison boundaries. The current ChEMBL 37 validation uses 2,897,819 source records and records more than 2.9 billion matching checks with zero blocking mismatch across the consolidated covered surfaces. A mismatch inside a declared parity boundary remains unfinished compatibility rather than being absorbed into an aggregate success percentage.&lt;/p&gt;

&lt;p&gt;The exact validation methodology deserves a separate article. The important point here is simpler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source semantics
        ↓
redesigned Rust architecture
        ↓
independent differential evidence

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The redesign is not asking readers to trust architectural intent alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Value Semantics Become Batch Semantics
&lt;/h2&gt;

&lt;p&gt;The same design choices become especially useful once the unit of work is no longer one molecule.&lt;/p&gt;

&lt;p&gt;Rust makes parallel iteration easy.&lt;/p&gt;

&lt;p&gt;That does not automatically make a cheminformatics API batch-native.&lt;/p&gt;

&lt;p&gt;Real dataset processing also needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stable input ordering,&lt;/li&gt;
&lt;li&gt;per-record failures,&lt;/li&gt;
&lt;li&gt;selection and filtering,&lt;/li&gt;
&lt;li&gt;output correspondence,&lt;/li&gt;
&lt;li&gt;parallel scheduling,&lt;/li&gt;
&lt;li&gt;reproducible composition.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The value-oriented molecular model gives this abstraction a natural foundation.&lt;/p&gt;

&lt;p&gt;If transformations already operate as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;molecule value
      ↓
new molecule value

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then a batch can extend the same idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ordered molecular values
          ↓
ordered transformed values
          +
per-record failure state

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;COSMolKit exposes this through &lt;code&gt;MoleculeBatch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MoleculeBatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_smiles_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CCO&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;c1ccccc1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not-smiles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keep&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;with_parallel_jobs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;prepared&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;batch&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_hydrogens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keep&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_2d_coordinates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keep&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prepared&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;valid_mask&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prepared&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important abstraction is not merely multiple threads.&lt;/p&gt;

&lt;p&gt;It is that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10,000 molecules
+
37 failures

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can remain a structured dataset state instead of becoming an exception-handling accident.&lt;/p&gt;

&lt;p&gt;Record correspondence remains visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input[0] ───────────── output[0]
input[1] ───────────── output[1]
input[2] ─ failed ──── error[2]
input[3] ───────────── output[3]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why batch processing belongs in the architectural story.&lt;/p&gt;

&lt;p&gt;Value semantics are not only about making scalar code aesthetically cleaner.&lt;/p&gt;

&lt;p&gt;They provide a much better foundation for ordered, isolated, failure-aware transformations over large molecular collections.&lt;/p&gt;

&lt;p&gt;The batch layer is still evolving, and not every batch surface is claimed as fully closed. But the direction follows naturally from the same state model rather than being added later as a collection of parallel wrappers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What “Rust-Native” Means Here
&lt;/h2&gt;

&lt;p&gt;A narrow definition of Rust-native cheminformatics would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;no C++
+
builds with Cargo
=
Rust-native

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is useful, but incomplete.&lt;/p&gt;

&lt;p&gt;For COSMolKit, Rust-native also means taking Rust’s software model seriously:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ownership should be visible;&lt;/li&gt;
&lt;li&gt;molecular values should not alias unexpectedly;&lt;/li&gt;
&lt;li&gt;mutation should be explicit;&lt;/li&gt;
&lt;li&gt;writable state should have controlled authority;&lt;/li&gt;
&lt;li&gt;index-changing edits should have migration semantics;&lt;/li&gt;
&lt;li&gt;derived state should have explicit lifetimes;&lt;/li&gt;
&lt;li&gt;failure behavior should be visible;&lt;/li&gt;
&lt;li&gt;batch workflows should be structural rather than incidental.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this makes the chemistry “more Rust-like.”&lt;/p&gt;

&lt;p&gt;That is not the objective.&lt;/p&gt;

&lt;p&gt;The objective is to make chemical software easier to reason about without giving up the semantics that took mature libraries decades to establish.&lt;/p&gt;

&lt;p&gt;That brings us back to the two correctness problems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chemical correctness
+
software-state correctness

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reference semantics address the first.&lt;/p&gt;

&lt;p&gt;Rust ownership and COSMolKit’s state architecture address the second.&lt;/p&gt;

&lt;p&gt;A robust molecular toolkit needs both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond RDKit Bindings
&lt;/h2&gt;

&lt;p&gt;FFI remains an excellent solution when an application simply needs mature RDKit functionality from Rust.&lt;/p&gt;

&lt;p&gt;COSMolKit is exploring a different design space.&lt;/p&gt;

&lt;p&gt;The aim is to preserve source-defined chemistry where compatibility matters while being willing to redesign the system around it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      RDKit-compatible semantics
                |
                v
       source-backed chemistry
                |
                v
       Rust molecular values
                |
        +-------+--------+
        |       |        |
     explicit  state   copy-on-write
     mutation  rules
        |       |        |
        +-------+--------+
                v
      scalar + batch workflows

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is what “beyond bindings” means here.&lt;/p&gt;

&lt;p&gt;Not abandoning RDKit.&lt;/p&gt;

&lt;p&gt;Not pretending decades of chemical edge cases can be reconstructed from a feature list.&lt;/p&gt;

&lt;p&gt;And not reproducing a historical object architecture merely because we want the chemistry implemented inside it.&lt;/p&gt;

&lt;p&gt;The opportunity for Rust cheminformatics is to separate those concerns:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Keep the semantics that are difficult to rediscover. Redesign the architecture that we now know how to make safer.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next articles in this series go deeper into the two systems that make this separation practical: executable operation contracts for agent-driven molecular-state changes, and source-backed porting discipline for reproducing RDKit semantics without accumulating heuristic semantic debt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repository References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/cosmol-studio/COSMolKit" rel="noopener noreferrer"&gt;Source repository&lt;/a&gt; ·&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kit.cosmol.org/" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt; ·&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tools.cosmol.org/" rel="noopener noreferrer"&gt;Web tools&lt;/a&gt; ·&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://crates.io/crates/cosmolkit" rel="noopener noreferrer"&gt;Rust crate&lt;/a&gt; ·&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pypi.org/project/cosmolkit/" rel="noopener noreferrer"&gt;Python package&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rust</category>
      <category>cheminformatics</category>
      <category>opensource</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
