Skip to content

fix: SMILES cache collision, multi-bond rendering, and identifier restore crash - #46

Merged
djleamen merged 4 commits into
mainfrom
claude/awesome-planck-ri4z2w
Oct 18, 2026
Merged

djleamen merged 4 commits into
mainfrom
claude/awesome-planck-ri4z2w

Conversation

@djleamen

Copy link
Copy Markdown
Owner

Summary

Three independent correctness fixes found during a cross-repo code-quality sweep, one per commit.

1. fix(lookup): SMILES cache key collided case-insensitively

getCacheKey lowercased the whole identifier value, but SMILES is case-sensitive — uppercase C is aliphatic carbon, lowercase c is aromatic. Looking up benzene (c1ccccc1) and then cyclohexane (C1CCCCC1) both mapped to smiles:c1ccccc1, so the second lookup returned benzene's cached identifiers (CAS 71-43-2, IUPAC name, PubChem CID 241) for cyclohexane and merged them into history. Now SMILES keys preserve case, matching the case-sensitive handling already in getLocalIdentifiers and moleculeParser.

2. fix(viewer): double/triple bonds offset along the wrong axis

Molecule3DComponent separated the parallel cylinders of a multi-bond by adding the offset to world X (position[0]) only. For a bond aligned with the X axis, the cylinders were shifted along the bond instead of beside it, so they overlapped and poked past the atoms — e.g. CO₂ (O=C=O, a built-in Quick Example with all atoms colinear on X) rendered both double bonds wrong. Now a unit vector perpendicular to each bond is computed (with a fallback axis for vertical bonds) and the cylinders are offset along it.

3. fix(form): restoring an older stored entry could white-screen the app

loadHistory/loadFavourites only validate that the parsed value is an array, not the shape of each entry's identifiers. The identifier set has grown over time, so restoring a history/favourite entry saved by an older build (or any hand-edited localStorage) could leave a field undefined; InputForm then called .trim() on it and threw, blanking the app since there's no error boundary. The read sites now default missing fields to ''.

Testing

  • npm run build (tsc && vite build) — succeeds, no type errors. (Pre-existing unrelated BatchedMesh/chunk-size warnings only.)
  • npx eslint on the three changed files with --max-warnings 0 — clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_0179jy7dFsNKpjfEQCmeQTQE


Generated by Claude Code

getCacheKey lowercased the whole value, but SMILES is case-sensitive
(uppercase 'C' is aliphatic carbon, lowercase 'c' is aromatic). Looking
up benzene ('c1ccccc1') and then cyclohexane ('C1CCCCC1') collided on the
key 'smiles:c1ccccc1', so the cache returned benzene's identifiers (CAS,
IUPAC name, PubChem CID) for cyclohexane and merged them into history.

Preserve case for SMILES keys, mirroring getLocalIdentifiers and
moleculeParser which already special-case SMILES.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_0179jy7dFsNKpjfEQCmeQTQE
Double and triple bonds separated their parallel cylinders by adding the
offset to world X (position[0]) only. For a bond aligned with the X axis
the cylinders were offset *along* the bond instead of beside it, so they
overlapped and poked past the atoms. CO2 (O=C=O, a built-in example with
all atoms colinear on X) rendered both double bonds incorrectly.

Compute a unit vector perpendicular to each bond (falling back to another
axis for vertical bonds) and offset the parallel cylinders along it.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_0179jy7dFsNKpjfEQCmeQTQE
loadHistory/loadFavourites only validate that the stored value is an
array, not the shape of each entry's identifiers. The ChemicalIdentifiers
set has grown over time, so restoring a history/favourite entry saved by
an older build (or any hand-edited localStorage) could leave a field
undefined. InputForm then called .trim() on it, throwing and white-
screening the app with no error boundary.

Default missing identifier fields to '' at the read sites.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_0179jy7dFsNKpjfEQCmeQTQE
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

The perpendicular-offset fix rendered double/triple bonds with four
near-identical Cylinder + meshStandardMaterial blocks and repeated the
three-axis offset math inline, which tripped SonarCloud's new-code
duplication gate. Extract a BondCylinder component and a shiftAlong
helper and collapse the single/double/triple cases to use them. No
rendering change: a double bond is still two offset cylinders and a
triple is a centered cylinder plus two offset ones.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_0179jy7dFsNKpjfEQCmeQTQE
@sonarqubecloud

Copy link
Copy Markdown

@djleamen
djleamen merged commit fd54205 into main Oct 18, 2026
9 checks passed
@djleamen
djleamen deleted the claude/awesome-planck-ri4z2w branch October 18, 2026 06:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants