<?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 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>
