smiles-js 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/IMPLEMENTATION_STATUS.md +45 -446
  2. package/package.json +1 -1
  3. package/src/codegen.js +130 -43
  4. package/src/constructors.js +471 -61
  5. package/src/decompiler.js +45 -3
  6. package/src/decompiler.test.js +23 -23
  7. package/src/fragment.test.js +1 -1
  8. package/src/index.js +1 -1
  9. package/src/manipulation.js +3 -2
  10. package/src/parser.js +49 -2
  11. package/test-integration/acetaminophen.smiles.js +20 -8
  12. package/test-integration/acetaminophen.test.js +26 -22
  13. package/test-integration/adjuvant-analgesics.test.js +507 -70
  14. package/test-integration/endocannabinoids.test.js +629 -42
  15. package/test-integration/hypertension-medication.smiles.js +1 -12
  16. package/test-integration/hypertension-medication.test.js +665 -59
  17. package/test-integration/local-anesthetics.test.js +827 -82
  18. package/test-integration/nsaids-otc.test.js +524 -64
  19. package/test-integration/nsaids-prescription.test.js +962 -89
  20. package/test-integration/opioids.test.js +857 -63
  21. package/test-integration/steroids.test.js +1955 -74
  22. package/test-integration/utils.js +14 -3
  23. package/test-integration/broken-molecules.test.js +0 -170
  24. package/test-integration/celecoxib.test.js +0 -199
  25. package/test-integration/ketoprofen-debug.test.js +0 -80
  26. package/test-integration/linear-bonds.test.js +0 -29
  27. package/test-integration/oxycodone.test.js +0 -99
  28. package/test-integration/sulfonamide-debug.test.js +0 -81
  29. package/test-integration/telmisartan.smiles.js +0 -11
  30. package/test-integration/telmisartan.test.js +0 -202
  31. package/test-integration/thc-debug.test.js +0 -46
@@ -1,464 +1,63 @@
1
1
  # Implementation Status
2
2
 
3
- ## ✅ FIXED: Double Bonds in Rings Now Preserved
4
-
5
- **Double bonds in rings are now correctly preserved during parsing/regeneration.**
6
-
7
- ```
8
- Input: C1=CC=CC=C1 → Output: C1=CC=CC=C1 (bonds PRESERVED)
9
- ```
10
-
11
- ### Naphthalene - WORKS
12
- ```
13
- Input: C1=CC2=CC=CC=C2C=C1
14
- Output: C1=CC2=CC=CC=C2C=C1
15
- ```
16
-
17
- ### Simple Benzimidazole - WORKS
18
- ```
19
- Input: C1=NC2=CC=CC=C2N1
20
- Output: C1=NC2=CC=CC=C2N1
21
- ```
22
-
23
- ---
24
-
25
- ## ✅ FIXED: Rings Inside Branches
26
-
27
- **Rings that appear inside branches (as attachments) are now correctly parsed and regenerated.**
28
-
29
- ### Biphenyl in branch - WORKS
30
- ```
31
- Input: c1ccc(c2ccccc2)cc1
32
- Output: c1ccc(c2ccccc2)cc1
33
- ```
34
-
35
- ### Fused ring inside branch - WORKS
36
- ```
37
- Input: C(c1nc2ccccc2n1)C
38
- Output: C(c1nc2ccccc2n1)C
39
- ```
40
-
41
- ### Nested fused ring with trailing atom - WORKS
42
- ```
43
- Input: c1ccc(C5=NC6=CC=CC=C6N5C)cc1
44
- Output: c1ccc(C5=NC6=CC=CC=C6N5C)cc1
45
- ```
46
-
47
- ---
48
-
49
- ## ✅ FIXED: Ring Closures Inside Branches
50
-
51
- **Ring closures that occur at different branch depths than where the ring opened are now handled correctly.**
52
-
53
- ### Ring closure inside branch of ring - WORKS
54
- ```
55
- Input: C1=NC2=C(CC2N1)C
56
- Output: C1=NC2=C(CC2N1)C
57
- ```
58
-
59
- ### Simple ring closure at different depth - WORKS
60
- ```
61
- Input: C1CC(C1)
62
- Output: C1CCC1 (canonical cyclobutane)
63
- ```
64
-
65
- ### Piperidine with ring closure in branch - WORKS
66
- ```
67
- Input: C1CCN(CC1)C
68
- Output: C1CCN(CC1)C
69
- ```
70
-
71
- ---
72
-
73
- ## ✅ FIXED: Full Telmisartan Structure
74
-
75
- **The full telmisartan molecule with deeply nested ring systems now parses and round-trips correctly.**
76
-
77
- ### Telmisartan - WORKS
78
- ```
79
- Input: CCCC1=NC2=C(C=C(C=C2N1CC3=CC=C(C=C3)C4=CC=CC=C4C(=O)O)C5=NC6=CC=CC=C6N5C)C
80
- Output: CCCC1=NC2=C(C=C(C=C2N1CC3=CC=C(C=C3)C4=CC=CC=C4C(=O)O)C5=NC6=CC=CC=C6N5C)C
81
- ```
82
-
83
- ---
84
-
85
- ## ✅ FIXED: Steroid Polycyclic Structures
86
-
87
- **Complex polycyclic steroids with shared atoms now parse correctly. Fixed duplicate attachment bug on shared fused ring atoms.**
88
-
89
- ### Cortisone - WORKS
90
- ```
91
- Input: CC12CCC(=O)C=C1CCC1C2C(O)CC2(C)C(C(=O)CO)CCC12
92
- Output: CC12CCC(=O)C=C1CCC1C2C(O)CC2(C)C(C(=O)CO)CCC12
93
- ```
94
-
95
- ### Hydrocortisone - WORKS
96
- ```
97
- Input: CC12CCC(=O)C=C1CCC1C2C(O)CC2(C)C(C(=O)CO)CCC12O
98
- Output: CC12CCC(=O)C=C1CCC1C2C(O)CC2(C)C(C(=O)CO)CCC12O
99
- ```
100
-
101
- ### Prednisone - WORKS
102
- ```
103
- Input: CC12CC(=O)C=CC1=CC(O)C1C2CCC2(C)C(C(=O)CO)CCC12
104
- Output: CC12CC(=O)C=CC1=CC(O)C1C2CCC2(C)C(C(=O)CO)CCC12
105
- ```
106
-
107
- ### Prednisolone - WORKS
108
- ```
109
- Input: CC12CC(=O)C=CC1=CC(O)C1C2C(O)CC2(C)C(C(=O)CO)CCC12
110
- Output: CC12CC(=O)C=CC1=CC(O)C1C2C(O)CC2(C)C(C(=O)CO)CCC12
111
- ```
112
-
113
- ### Methylprednisolone - WORKS
114
- ```
115
- Input: CC12CC(=O)C(C)=CC1=CC(O)C1C2C(O)CC2(C)C(C(=O)CO)CCC12
116
- Output: CC12CC(=O)C(C)=CC1=CC(O)C1C2C(O)CC2(C)C(C(=O)CO)CCC12
117
- ```
118
-
119
- ### Dexamethasone - WORKS
120
- ```
121
- Input: CC1CC2C3CCC4=CC(=O)C=CC4(C)C3(F)C(O)CC2(C)C1(O)C(=O)CO
122
- Output: CC1CC2C3CCC4=CC(=O)C=CC4(C)C3(F)C(O)CC2(C)C1(O)C(=O)CO
123
- ```
124
-
125
- ---
126
-
127
- ## ✅ FIXED: Opioids (Piperidine-based)
128
-
129
- **Opioids with piperidine rings that close inside branches now work correctly.**
130
-
131
- ### Fentanyl - WORKS
132
- ```
133
- Input: CCC(=O)N(C1CCN(CC1)CCC2=CC=CC=C2)C3=CC=CC=C3
134
- Output: CCC(=O)N(C1CCN(CC1)CCC2=CC=CC=C2)C3=CC=CC=C3
135
- ```
136
-
137
- ### Tramadol - WORKS
138
- ```
139
- Input: CN(C)CC1CCCCC1(C2=CC(=CC=C2)OC)O
140
- Output: CN(C)CC1CCCCC1(C2=CC(=CC=C2)OC)O
141
- ```
142
-
143
- ---
144
-
145
- ## ✅ FIXED: Linear Chain Double Bonds
146
-
147
- **Double bonds in linear chains are now correctly preserved at their original positions.**
148
-
149
- ### Anandamide - WORKS
150
- ```
151
- Input: CCCCCC=CCC=CCC=CCC=CCCCC(=O)NCCO
152
- Output: CCCCCC=CCC=CCC=CCC=CCCCC(=O)NCCO
153
- ```
154
-
155
- ### 2-Arachidonoylglycerol - WORKS
156
- ```
157
- Input: CCCCCC=CCC=CCC=CCC=CCCCC(=O)OC(CO)CO
158
- Output: CCCCCC=CCC=CCC=CCC=CCCCC(=O)OC(CO)CO
159
- ```
160
-
161
- ---
162
-
163
- ## 🟡 Known Limitation: toCode() for Complex Structures
164
-
165
- The `toCode()` method (generating JS constructor code from AST) does not yet fully support complex nested structures with sequential continuation rings. The SMILES parsing and serialization works correctly, but the generated JavaScript code may not reproduce the full structure.
166
-
167
- ---
168
-
169
- ## Changes Made
170
-
171
- 1. Added `bonds` array to Ring AST node (like Linear nodes)
172
- 2. Parser now extracts bonds between ring atoms
173
- 3. Codegen serializes bonds in ring output
174
- 4. Fused ring codegen updated to preserve bonds
175
- 5. Fixed rings inside branches being excluded from attachments
176
- 6. Added branch depth normalization to fused ring codegen
177
- 7. Fixed sequential continuation atoms for trailing atoms after ring closures
178
- 8. Added unified iterative loop for collecting all inline positions (sequential continuations + afterBranchClose atoms)
179
- 9. Track sequential continuation rings separately for codegen
180
- 10. Store atom values for non-ring positions in `_atomValueMap`
181
- 11. Store attachments for sequential continuation atoms in `_seqAtomAttachments`
182
- 12. Fixed `lastAtomAtDepth` to clear when entering new branches (prevents cross-branch linking)
183
- 13. Fixed duplicate attachments on shared atoms in fused rings (positionsWithAttachments tracking)
184
- 14. Fixed ring marker placement - ring closures now come before attachments at closing position
185
- 15. Added `buildBranchCrossingRingSMILES` for rings that traverse branch boundaries
186
- 16. Fixed linear chain bonds - keep null values to preserve positional information
187
- 17. Added sequential continuation ring detection for single-ring groups (celecoxib pattern)
188
- 18. Converted all test assertions to exact value matching - no `toBeDefined()`, `typeof`, or `toHaveLength()` weak assertions
189
- 19. Fixed deeply nested branches with multiple rings being lost (Valsartan, biphenyl patterns)
190
- 20. Fixed sequential non-fused rings in branches being skipped (changed `atomToGroup.has()` to `atomToGroup.get() === groupIdx`)
191
- 21. Fixed bracket atom serialization - use `atom.rawValue` instead of `atom.value.raw` to preserve `[nH]` notation
192
-
193
- ---
194
-
195
- ## ✅ FIXED: Complex Morphinan Structures (Oxycodone)
196
-
197
- **Oxycodone and related morphinans now work correctly:**
198
- ```
199
- Input: CN1CCC23C4C(=O)CCC2(C1CC5=C3C(=C(C=C5)OC)O4)O
200
- Output: CN1CCC23C4C(=O)CCC2(C1CC5=C3C(=C(C=C5)OC)O4)O
201
- ```
202
-
203
- The fix involved:
204
- 1. Detecting "bridge rings" that share atoms with main chain rings but are at different branch depths
205
- 2. Including these bridge rings in the fused ring group
206
- 3. Properly excluding bridge ring atoms from being treated as attachments
207
- 4. Updating `allRingPositions` when sequential continuation rings are discovered
208
-
209
- ### All Morphinans - NOW WORKING
210
- ```
211
- Morphine: CN1CCC23C4OC5=C(O)C=CC(=C25)C(O)C=CC3C1C4
212
- Codeine: CN1CCC23C4OC5=C(OC)C=CC(=C25)C(O)C=CC3C1C4
213
- Hydrocodone: CN1CCC23C4OC5=C(OC)C=CC(=C25)C(=O)CCC3C1C4
214
- Hydromorphone: CN1CCC23C4OC5=C(O)C=CC(=C25)C(=O)CCC3C1C4
215
- ```
216
-
217
- ---
218
-
219
- ## ✅ FIXED: Additional NSAIDs (After Oxycodone Fix)
220
-
221
- These NSAIDs started working after the bridge ring detection fix:
222
-
223
- ### Rofecoxib - NOW WORKING
224
- ```
225
- Input: CS(=O)(=O)C1=CC=C(C=C1)C2=C(C(=O)OC2)C3=CC=CC=C3
226
- Output: CS(=O)(=O)C1=CC=C(C=C1)C2=C(C(=O)OC2)C3=CC=CC=C3
227
- ```
228
-
229
- ### Etoricoxib - NOW WORKING
230
- ```
231
- Input: CC1=NC=C(C=C1)C2=CC=C(C=C2)S(=O)(=O)C3=CC=CC=C3
232
- Output: CC1=NC=C(C=C1)C2=CC=C(C=C2)S(=O)(=O)C3=CC=CC=C3
233
- ```
234
-
235
- ### Nabumetone - NOW WORKING
236
- ```
237
- Input: COC1=CC2=CC(=CC=C2C=C1)CCC(=O)C
238
- Output: COC1=CC2=CC(=CC=C2C=C1)CCC(=O)C
239
- ```
240
-
241
- ### Ketoprofen - NOW WORKING
242
- ```
243
- Input: CC(c1cccc(c1)C(=O)c2ccccc2)C(=O)O
244
- Output: CC(c1cccc(c1)C(=O)c2ccccc2)C(=O)O
245
- ```
246
-
247
- ### Ibuprofen - NOW WORKING
248
- ```
249
- Input: CC(C)Cc1ccc(cc1)C(C)C(=O)O
250
- Output: CC(C)Cc1ccc(cc1)C(C)C(=O)O
251
- ```
252
-
253
- ### Benzocaine - NOW WORKING
254
- ```
255
- Input: CCOC(=O)C1=CC=C(C=C1)N
256
- Output: CCOC(=O)C1=CC=C(C=C1)N
257
- ```
258
-
259
- ---
260
-
261
- ## ✅ FIXED: Sequential Continuation Rings (Celecoxib Pattern)
262
-
263
- **Rings that open inside a branch containing another ring's closure are now handled correctly.**
264
-
265
- This pattern occurs when:
266
- - Ring 1 closes at a certain branch depth
267
- - Ring 2 opens immediately after at the same branch depth
268
- - Ring 2 needs to be processed together with Ring 1
269
-
270
- ### Celecoxib - NOW WORKING
271
- ```
272
- Input: CC1=CC=C(C=C1)C2=CC(=NN2C3=CC=C(C=C3)S(=O)(=O)N)C(F)(F)F
273
- Output: CC1=CC=C(C=C1)C2=CC(=NN2C3=CC=C(C=C3)S(=O)(=O)N)C(F)(F)F
274
- ```
275
-
276
- ### Minimal Pattern Example
277
- ```
278
- Input: C1CC(C1C2CCC2)C (Ring 2 opens inside branch after Ring 1 closes)
279
- Output: C1CC(C1C2CCC2)C
280
- ```
281
-
282
- The fix detects when a single ring closes at a deeper branch level and recursively includes immediately following rings that are at the same branch depth (without `afterBranchClose` flag).
283
-
284
- ---
285
-
286
- ## ✅ FIXED: Deeply Nested Branches with Multiple Rings
287
-
288
- **Fixed issues with parser losing deeply nested branches containing rings.**
289
-
290
- ### Valsartan - NOW WORKING
291
- ```
292
- Input: CCCCC(=O)N(CC1=CC=CC=C1C2=CC=CC=C2C3=NNN=N3)C(C(C)C)C(=O)O
293
- Output: CCCCC(=O)N(CC1=CC=CC=C1C2=CC=CC=C2C3=NNN=N3)C(C(C)C)C(=O)O
294
- ```
295
-
296
- ### Ketoprofen (Biphenyl Variant) - NOW WORKING
297
- ```
298
- Input: CC(c1ccccc1c2ccccc2)C(=O)O
299
- Output: CC(c1ccccc1c2ccccc2)C(=O)O
300
- ```
301
-
302
- The fix involved two changes:
303
- 1. **Sequential rings at different depths**: The code for handling sequential continuation atoms was excluding ALL atoms from other rings. Changed to only exclude atoms from **sibling rings** (same branch depth), while properly including atoms from **attachment rings** (deeper branch depths).
304
-
305
- 2. **Sequential rings in the same branch**: The loop that skips atoms after processing a ring group was skipping atoms from ALL groups instead of just the current group. Changed `atomToGroup.has(...)` to `atomToGroup.get(...) === groupIdx` to only skip atoms in the same group.
306
-
307
- ---
308
-
309
- ## ✅ FIXED: Cannabinoid Tricyclic Structures
310
-
311
- **All cannabinoids now work after the deeply nested branch fixes:**
312
-
313
- ### THC - NOW WORKING
314
- ```
315
- Input: CCCCCC1=CC(=C2C3C=C(CCC3C(OC2=C1)(C)C)C)O
316
- Output: CCCCCC1=CC(=C2C3C=C(CCC3C(OC2=C1)(C)C)C)O
317
- ```
318
-
319
- ### CBD - NOW WORKING
320
- ```
321
- Input: CCCCCC1=CC(=C(C(=C1)O)C2C=C(CCC2C(=C)C)C)O
322
- Output: CCCCCC1=CC(=C(C(=C1)O)C2C=C(CCC2C(=C)C)C)O
323
- ```
324
-
325
- ### Nabilone - NOW WORKING
326
- ```
327
- Input: CCCCCCC(C)(C)C1=CC(=C2C3CC(=O)CCC3C(OC2=C1)(C)C)O
328
- Output: CCCCCCC(C)(C)C1=CC(=C2C3CC(=O)CCC3C(OC2=C1)(C)C)O
329
- ```
330
-
331
- ---
332
-
333
- ## ✅ FIXED: Complex Heterocyclic NSAIDs
334
-
335
- **All complex heterocyclic NSAIDs now work:**
336
-
337
- ### Meloxicam - NOW WORKING
338
- ```
339
- Input: CC1=C(N=C(S1)NC(=O)C2=C(C3=CC=CC=C3S(=O)(=O)N2C)O)C
340
- Output: CC1=C(N=C(S1)NC(=O)C2=C(C3=CC=CC=C3S(=O)(=O)N2C)O)C
341
- ```
342
-
343
- ### Piroxicam - NOW WORKING
344
- ```
345
- Input: CN1C(=C(C2=CC=CC=C2S1(=O)=O)O)C(=O)NC3=CC=CC=N3
346
- Output: CN1C(=C(C2=CC=CC=C2S1(=O)=O)O)C(=O)NC3=CC=CC=N3
347
- ```
348
-
349
- ### Oxaprozin - NOW WORKING
350
- ```
351
- Input: OC(=O)CCC1=NC(=C(O1)C2=CC=CC=C2)C3=CC=CC=C3
352
- Output: OC(=O)CCC1=NC(=C(O1)C2=CC=CC=C2)C3=CC=CC=C3
353
- ```
354
-
355
- ---
356
-
357
- ## ✅ FIXED: Bracket Atom Serialization
358
-
359
- **Bracket atoms like `[nH]` are now correctly preserved during parsing/regeneration.**
360
-
361
- ### Losartan - WORKS
362
- ```
363
- Input: CCCCc1nc(Cl)c(n1Cc2ccc(cc2)c3ccccc3c4n[nH]nn4)CO
364
- Output: CCCCc1nc(Cl)c(n1Cc2ccc(cc2)c3ccccc3c4n[nH]nn4)CO
365
- ```
366
-
367
- The fix involved using `atom.rawValue` (which stores the full bracket notation like `"[nH]"`) instead of `atom.value.raw` (which only stores the inner content like `"nH"`).
368
-
369
- ---
370
-
371
3
  ## Test Coverage
4
+ - **468 tests passing** across 18 test files
5
+ - 778 expect() calls with exact value matching
6
+ - All tests run in ~173ms
372
7
 
373
- - 457 tests passing across 25 test files
374
- - 0 tests skipped
375
- - Tests cover parsing, code generation, and round-trip validation
376
- - All test assertions use exact value matching (`.toEqual()`, `.toBe()`) - no weak assertions
8
+ ## Supported Molecule Classes
377
9
 
378
- ---
10
+ | Category | Examples | Status |
11
+ |----------|----------|--------|
12
+ | NSAIDs | Ibuprofen, Naproxen, Celecoxib, Meloxicam, Piroxicam | ✅ |
13
+ | Opioids | Fentanyl, Tramadol, Morphine, Codeine, Oxycodone | ✅ |
14
+ | Steroids | Cortisone, Hydrocortisone, Prednisone, Dexamethasone | ✅ |
15
+ | Cannabinoids | THC, CBD, Nabilone | ✅ |
16
+ | Hypertension | Losartan, Valsartan, Telmisartan | ✅ |
17
+ | Analgesics | Acetaminophen, Phenacetin, Gabapentin, Pregabalin | ✅ |
18
+ | Endocannabinoids | Anandamide, 2-AG | ✅ |
379
19
 
380
- ## Production Readiness: ✅ READY FOR v1.0.0
20
+ ## API Completeness
381
21
 
382
- **Audit Date**: 2026-01-30
383
- **Status**: All planned features implemented and tested
22
+ **Constructors**: Ring, Linear, FusedRing, Molecule, Fragment
384
23
 
385
- ### Implementation Roadmap Status: 21/21 Checkpoints Complete
24
+ **Ring Methods**: attach, substitute, substituteMultiple, fuse, concat, clone
386
25
 
387
- | Checkpoint | Feature | Status | Verification |
388
- |------------|---------|--------|--------------|
389
- | 0 | Foundation (AST types, constructors) | ✅ DONE | Files exist, tests passing |
390
- | 1 | Ring Constructor | ✅ DONE | `Ring({ atoms: 'c', size: 6 }).smiles === 'c1ccccc1'` |
391
- | 2 | Linear Constructor | ✅ DONE | `Linear(['C', 'C', 'C']).smiles === 'CCC'` |
392
- | 3 | Ring.attach() | ✅ DONE | `benzene.attach(methyl, 1).smiles` works |
393
- | 4 | Ring.substitute() | ✅ DONE | `benzene.substitute(5, 'n').smiles === 'c1cccnc1'` |
394
- | 5 | Molecule Constructor | ✅ DONE | `Molecule([propyl, benzene]).smiles` works |
395
- | 6 | FusedRing Constructor | ✅ DONE | Naphthalene round-trips correctly |
396
- | 7 | SMILES Code Generator | ✅ DONE | `src/codegen.js` complete, all `.smiles` getters work |
397
- | 8 | Ring Manipulation Methods | ✅ DONE | All methods implemented: `substituteMultiple`, `fuse`, `concat`, `clone` |
398
- | 9 | FusedRing Manipulation | ✅ DONE | All methods implemented: `addRing`, `getRing`, `substituteInRing`, etc. |
399
- | 10 | Linear & Molecule Manipulation | ✅ DONE | All methods implemented: `attach`, `branch`, `concat`, `append`, etc. |
400
- | 11 | Tokenizer (Phase 1) | ✅ DONE | `tokenize()` works, 29 tests passing |
401
- | 12 | Parser Pass 1 - Linear Scan | ✅ DONE | `buildAtomList()` implemented |
402
- | 13 | Parser Pass 2 - AST Building | ✅ DONE | Complex molecules (telmisartan) parse correctly |
403
- | 14 | Fragment Integration | ✅ DONE | `Fragment('c1ccccc1')` works with new parser |
404
- | 15 | Round-Trip Validation | ✅ DONE | 457 tests verify round-trip fidelity |
405
- | 16 | Decompiler - Basic | ✅ DONE | `decompile()` works for simple structures |
406
- | 17 | Decompiler - Complete | ✅ DONE | All node types decompile (with documented limitation) |
407
- | 18 | Decompiler - Fragment Integration | ✅ DONE | `fragment.toCode()` method works |
408
- | 19 | Documentation & Examples | ✅ DONE | README, docs/, inline comments, 32+ molecule examples |
409
- | 20 | Performance & Optimization | ✅ DONE | 457 tests run in ~163ms, efficient parsing |
410
- | 21 | Final Testing & Release | ✅ DONE | 100% test pass rate, edge cases covered |
26
+ **Linear Methods**: attach, concat, branch, branchAt, clone
411
27
 
412
- ### API Completeness: 100%
28
+ **FusedRing Methods**: addRing, getRing, substituteInRing, attachToRing, renumber, concat, clone
413
29
 
414
- **Construction API**: Ring | Linear | FusedRing ✅ | Molecule ✅
415
- **Ring Manipulation**: attach ✅ | substitute ✅ | substituteMultiple ✅ | fuse ✅ | concat ✅ | clone ✅
416
- **Linear Manipulation**: attach ✅ | concat ✅ | branch ✅ | branchAt ✅ | clone ✅
417
- **FusedRing Manipulation**: addRing ✅ | getRing ✅ | substituteInRing ✅ | attachToRing ✅ | renumber ✅ | concat ✅ | clone ✅
418
- **Molecule Manipulation**: append ✅ | prepend ✅ | concat ✅ | getComponent ✅ | replaceComponent ✅ | clone ✅
419
- **Parsing/Serialization**: tokenize ✅ | parse ✅ | buildSMILES ✅ | decompile ✅ | .smiles getters ✅ | .toCode() ✅
30
+ **Molecule Methods**: append, prepend, concat, getComponent, replaceComponent, clone
420
31
 
421
- ### Quality Metrics
32
+ **Parsing**: tokenize, parse, buildSMILES, decompile, .smiles getters, .toCode()
422
33
 
423
- - **Test Coverage**: 457/457 tests passing (100%)
424
- - **Test Files**: 25 files with comprehensive coverage
425
- - **Assertions**: 694 exact assertions (no weak checks)
426
- - **Complex Molecules Verified**: 32+ drugs (steroids, opioids, NSAIDs, cannabinoids)
427
- - **Round-Trip Fidelity**: All structures round-trip correctly
428
- - **Code Quality**: Clean architecture, immutable operations, no global state
429
- - **Documentation**: README + design docs + API examples + inline comments
34
+ ## Implementation Checkpoints: 21/21
430
35
 
431
- ### Known Limitation ⚠️
36
+ All planned features implemented:
37
+ - Foundation (AST types, constructors)
38
+ - Ring/Linear/FusedRing/Molecule constructors and manipulation
39
+ - SMILES tokenizer and parser
40
+ - Code generator (AST → SMILES)
41
+ - Decompiler (AST → JavaScript)
42
+ - Fragment integration
43
+ - Round-trip validation
44
+ - Documentation and examples
432
45
 
433
- **toCode() for Sequential Continuation Patterns**: The decompiler has a documented limitation when generating JavaScript code for certain complex nested structures. This does NOT affect parsing or serialization - only code generation.
46
+ ## Known Limitation
434
47
 
435
- **What works perfectly**:
48
+ **toCode() for complex nested structures**: The decompiler cannot generate JavaScript code for certain sequential continuation patterns. This does NOT affect:
436
49
  - ✅ Parsing SMILES → AST
437
50
  - ✅ Serializing AST → SMILES
438
- - ✅ Round-trip fidelity (SMILES → AST → SMILES)
439
-
440
- **What has limitations**:
441
- - ⚠️ Generating JS code for sequential continuation patterns (AST → JavaScript)
442
-
443
- **Assessment**: Acceptable for v1.0.0 because:
444
- 1. Core functionality (parse/serialize) is perfect
445
- 2. Limitation only affects developer tooling
446
- 3. Clearly documented
447
- 4. Most users will use programmatic API directly
448
-
449
- ### Production Deployment Checklist
450
-
451
- - [x] All planned features implemented (21/21 checkpoints)
452
- - [x] Comprehensive test suite (457 tests, 0 failures)
453
- - [x] Documentation complete (README, design docs, examples)
454
- - [x] Known limitations documented
455
- - [x] API stable and consistent
456
- - [x] Performance validated (~163ms for 457 tests)
457
- - [x] Complex real-world molecules tested
458
- - [x] Round-trip validation verified
459
- - [x] Code quality high (modular, immutable, clean)
460
- - [x] No critical bugs
461
-
462
- ### Recommendation: Ship v1.0.0 ✅
463
-
464
- The library is **production ready** and suitable for v1.0.0 release. All core features are implemented, tested, and documented. The single known limitation (toCode() for complex patterns) is clearly documented and does not affect primary use cases.
51
+ - ✅ Round-trip fidelity
52
+
53
+ ## Key Fixes Implemented
54
+
55
+ 1. Double bonds in rings preserved
56
+ 2. Rings inside branches handled correctly
57
+ 3. Ring closures at different branch depths
58
+ 4. Steroid polycyclic structures (shared atoms)
59
+ 5. Sequential continuation rings (celecoxib pattern)
60
+ 6. Deeply nested branches with multiple rings
61
+ 7. Bracket atom serialization (`[nH]`)
62
+ 8. Linear chain double bond positions
63
+ 9. Bridge ring detection for morphinans
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smiles-js",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "A JavaScript library for building molecules using composable fragments",
5
5
  "type": "module",
6
6
  "main": "src/index.js",