Skip to content

Roadmap ​

xtalforge reproduces everything the headless core of Crystal-Builder does (the xtal/ package; the xtalapp/ GUI is out of scope) as a pure Rust library, with four surfaces developed at the same pace: Rust API, CLI, Python, WebAssembly.

Each phase has its own file. Inside a phase, work is split into numbered tasks (N.M) and each task into subtasks (N.M.K) with a checkbox. A subtask is ticked only when implementation, tests, all four surfaces (when user-visible) and documentation are done. The rules that govern all of this are in AGENTS.md at the repository root.

Phases ​

PhaseFileGoalRelease gate
0FoundationsWorkspace, rules, CI, docs site, moyo audit, sci-form reuse plan, dependency replacement map, binding architecture, golden-data oraclenone (remaining work)
1CoreElements, lattice, structure, P1, supercell, slab, neighbors, bonding, rings, groups, measures, limits, CIF/POSCAR/XYZwith Task 2.1: v0.0.1
2Symmetrymoyo integration, space groups, Wyckoff, standard cells, reduction, subgroups, point groups, Brillouin zone and k-pathv0.0.x
3Formats, commands, view dataAll file formats, project files, undo/redo commands, selection, tracking, workspace, view settings and scene data, STLv0.0.x
4Force fieldsCalculator API, UFF/UFF4MOF, QEq/EQeq, Ewald, optimizers, scans, vibrations, phonons, thermodynamics, Prepare for simulation, external enginesv0.1.0
5AnalysisPXRD, grids, porosity and accessibility, topology and RCSR, merged nets, interpenetration, overlays, module registry and reportsv0.y
6BuildersMolecules, substituents, fill, carbon, graphene, nanotubes, fullerenes, polymers, MOF builderv0.y
7Powder refinementPattern data, peaks, indexing, Pawley, Rietveld, energy-weighted refinement, automatic runv0.y
8Agent and distributionSession verbs, inspection, MCP server, ML potentials, distribution, performance, API freezev1.0.0
9Core featuresStructure matcher, strain/rattle/site edits, Voronoi and coordination, BVS/oxidation states, RDF, unique Miller indices and terminations, Wulff, adsorption sites, defects, orderings/SQS, interfaces, elastic tensor, EOS, convex hullv1.2.0
10MOF platformMOF checker and cleaning, SBU/linker deconstruction, topology from structure, MOFid/MOFkey, open metal sites, native PLD/LCD/ASA, Widom/Henry/GCMC, PSM, MOF defects, CoRE MOF/QMOF screeningv1.3.0
11Usability audit and 1.x polishFix the 2026-11-11 usability findings, close the Rust-only parity gaps, deprecation mechanism, recipesv1.4.0
12Native bindingsObject API in Python and JS, NumPy, typed TS results, typed arrays, workersv1.5.0
13Ecosystem interoperabilityASE, pymatgen, phonopy, RDKit adapters; QE/CASTEP/VASP outputs/mmCIF/SDF; OPTIMADE, COD, MPv1.6.0
14Scientific completenessClose every known subset; instrument model, MD, full topologyv1.7.0
15Performance and scaleComparative benchmarks, million-atom structures, streaming IO, split WASMv1.8.0
16Workflows and provenanceDeclarative workflows, provenance, datasets, deduplication, ML descriptorsv1.9.0
172.0 redesign and freezeRemove deprecations, unified options and errors, schema v2, migration guidev2.0.0

Current status (2026-11-11) ​

  • Phases 0-10 are complete; the Rust API, CLI, Python and WASM surfaces build and pass their checks. v0.0.1, v0.0.2, v0.0.3, v1.0.0-rc.1, the stable v1.0.0, v1.1.0, v1.2.0 and v1.3.0 are published on crates.io, PyPI (xtalforge), npm (xtalforge-wasm), the GitHub release and GitHub Pages. v1.0.0 (2026-11-10) ships 13 crates, 7 wheels plus an sdist, the npm package and the hosted CLI assets; v1.1.0 (2026-11-11) adds the 3D playground and the end-to-end audit battery; v1.2.0 (2026-11-11) releases Phase 9, the core features of a standard crystal library; v1.3.0 (2026-11-12) releases the MOF platform.
  • Phase 8 is complete: xtalforge-agent (verbs, session, diagnostics, MCP, skill), plugins, the Python ML bridge, distribution, benchmarks, robustness, tutorials and the API freeze. Phase 9 is complete: comparison, edits, local environments, surfaces, defects and disorder, interfaces, elasticity, EOS fits and convex hulls on all four surfaces, with five algorithm pages. Phase 10 is complete: MOF checking and cleaning, deconstruction, MOFid, descriptors, native PLD/LCD/ASA, host-guest force fields, Widom, GCMC, RASPA export, PSM, defects, variants, databases and screening. Tasks 9.7.2, 10.5.7, 10.6.4 and 10.7.3-10.7.5 remain open. The stable API follows the SemVer policy and the known subsets below are the only documented reference gaps.
  • The release workflow is the only GitHub Actions workflow; the CI, rules and manual docs workflows were removed by maintainer decision (2026-11-08) to avoid runner cost. The release runs on a version tag: three CLI packages, PyPI/npm/crates.io from ubuntu-24.04, then the docs deployment. The github-pages environment allows main and the v* tag pattern.

Known subsets ​

The checkboxes record that the documented local subset is implemented, tested and exposed on the surfaces. The following reference behaviours are subsets or simplified ports rather than complete reproductions; they are the first candidates for Phase 8 or a follow-up and are not silent approximations:

  • 4.9: the DFTB+ parser is validated against a recorded DFTB+ output (crates/xtalforge-ff/tests/fixtures/dftb/si_scc_detailed.out), and the xTB GFN0/GFN1/GFN2 methods are available in-process through the sci-form feature. The external launchers still need a real binary, so a complete DFTB+/xTB run is not executed in CI; ORCA remains input-only by design.
  • 4.4: held cell lengths/volume (CellFreedom) and an external pressure term are not implemented; OptimizeOptions.cell relaxes the point-group-averaged strain only.
  • 5.1 and 7.2: the calculated PXRD uses one Gaussian per reflection and the Instrument has no wavelength or Caglioti U, V, W; Rietveld ignores RietveldOptions::kind (area-normalised Gaussian, K alpha doublet by ratio).
  • 5.x/7.x: the Pawley and Le Bail pseudo-Voigt mixing eta is a fixed option (0.5 by default), not a refined parameter, so a Gaussian pattern fitted with the default profile leaves a large Rwp (adding a refinable eta would change the frozen PawleyOptions struct).
  • 3.10 and 4.4: TransformCell, MakeSlab, AssignWyckoff, Invert, DescendToSubgroup, MergeDuplicates, InsertMolecules, ApplyOptimizedGeometry, AddHydrogens, Prepare and SetAtomTypes are not command types, and the Vinet equation of state is missing; the functions behind most of them exist and apply through ReplaceStructure.
  • 5.1-5.4: the PXRD has no anisotropic Debye-Waller factors, no pseudo-Voigt/Caglioti width, no monochromator option and a fixed radiation set; the porosity grid has no channel percolation, probe-occupiable volume or per-mass area; meshes have no normals or OBJ output.
  • 5.6-5.10: no structure-to-net contraction, vertex symbols, search by space group or transitivity, Blatov interpenetration classes, or HTML/JSON report renderers; the module registry has no CLI command.
  • 6.1-6.4: SMILES parsing and embedding, sketches, the fragment library, substitution and guest placement are Rust-only (no CLI, Python or WASM surface), see the open gaps in docs/api/parity.md.
  • 7.x: no whole-range peak refinement, TCH/Caglioti/FCJ profiles, persistent powder parameter sets, Pareto sweep or knee, run module steps, named instrument presets, indexing engine agreement, cancellation or powder demo.
  • 4.4-4.5: no cancellation or progress callback in the optimizers, no trajectory output, scan coordinates limited to atom-index distance, angle and torsion, and scans that neither write points to disk nor resume.
  • 1.8: Slab.cut is always zero; severed bonds are not carried through the cut.
  • 1.11: explicit bonds map to P1 indices and are not propagated to every symmetry image; pair-specific bond ranges and a metal-metal switch are not exposed.
  • 6.x: the MOF builder uses a curated topology/block subset and a greedy orientation instead of PORMAKE's global RMSD fit.
  • 9.1: the matcher works on Niggli-reduced input cells and accepts supercell relationships; it does not call the standardized primitive-cell path (which is a separate API and is being audited), so a conventional/primitive pair is matched by expanding the smaller cell.
  • 9.3: the Voronoi cutoff must contain every face of the cell (twice the longest nearest-neighbour distance is safe); shape measures cover the common polyhedra up to 12 vertices; the CrystalNN strategy is a documented solid-angle/distance approximation, not pymatgen's full bond-order model.
  • 9.4: terminations use midpoint cuts between atomic layers, so cuts inside a layer are not generated; adsorption sites are top/bridge/hollow on the uppermost layer only.
  • 9.5: point defects use Voronoi vertices as interstitial candidates; the ordering search caps the decorations (max_orderings) and ranks them with the in-process Ewald sum; SQS is binary and reports pair/triplet correlations, not a full cluster expansion.
  • 10.x: the curated six-topology/eight-block builder subset remains until the licensed PORMAKE data drop (Task 10.5.7); database readers work on an extracted directory, not a zip, and on-demand fetch is Task 10.6.4.
  • 10.2: deconstruction uses the all-node rule with metal-adjacent non-carbon atoms in the node; MOFid is a deterministic subset of the published syntax (unit graphs, topology, interpenetration) and MOFkey is its SHA-256.
  • 10.3: PLD/channel dimension are voxelized union-find results from the distance grid; they converge with the spacing and are not bit-identical to Zeo++.
  • 10.4: GCMC is single-component with rigid host/guest and an ideal-gas chemical potential; guest-guest interactions and Peng-Robinson fugacity are left to the RASPA export. Widom uses direct host-guest sums with a 15 A cutoff.
  • 9.6: the elastic tensor uses the stress finite differences of the native UFF calculator (any Calculator with stress works), and the EOS/hull fits are point estimates with parameter errors, without a global optimizer audit.
  • 8.x: every library error exits the CLI with code 3 and Python raises XtalforgeError (InputError for invalid input); the code string is the discriminator.

Release milestones ​

Version rules are defined in AGENTS.md section 5. In short:

  • v0.0.1 — Phase 1 complete plus Task 2.1 (moyo integration). The "essential core": read a CIF, expand it to P1, detect its space group, build supercells and slabs, perceive bonds and rings, write CIF/POSCAR/XYZ, all through Rust, CLI, Python and WASM, with docs and demos.
  • v0.0.x — one PATCH release per completed task group of Phases 2 and 3, and of Phase 4 until it is complete.
  • v0.1.0 — Phase 4 complete: force fields and optimizers usable.
  • v0.y.z — Phases 5 to 7; MINOR bump at each completed phase.
  • v1.0.0 — Phase 8 complete: API frozen, parity matrix closed, documentation complete.
  • v1.2.0 — Phase 9 complete: the core features of a standard crystal library beyond Crystal-Builder parity (released 2026-11-11).
  • v1.3.0 — Phase 10 complete: the MOF platform (focus of the 2.0 road; released 2026-11-12).
  • v1.4.0 … v1.9.0 — Phases 11 to 16, one MINOR release per completed phase; every change is backward compatible and anything to be removed is deprecated first (Task 11.4.2).
  • v2.0.0 — Phase 17 complete: deprecated surface removed, unified options and errors, schema version 2, after a 2.0.0-rc.N stabilization period.

Road to 2.0.0 (started 2026-11-11) ​

The goal is to make xtalforge the default crystal-structure library across Rust, Python, the CLI and the browser. The plan starts from the core gap check and usability audit of 2026-11-11 and orders the work by user impact. Focus: metal-organic frameworks (decided 2026-11-11): first the missing core operations (Phase 9), then the MOF platform (Phase 10), then remove friction (Phases 11-12), then meet users where they are (Phase 13), then close the science gaps (Phase 14), then scale (Phases 15-16), and only then break the API once (Phase 17). No other capability is dropped: the MOF focus sets priorities inside each phase (table at the end of Phase 10). Phases 9-16 may overlap; Phase 17 starts when they are complete or explicitly descoped with a Note:.

Cross-cutting requirements (apply to every phase) ​

  1. Every code file is at most 500 lines (Markdown exempt); data goes to data/.
  2. Language is unrestricted; the former English-only rule is retired (2026-11-08).
  3. Every user-visible subtask ships four surfaces and docs: Rust, CLI, Python, WASM, plus a VitePress API page, and an algorithm page or demo where it makes sense.
  4. Every ported algorithm is validated against Crystal-Builder or sci-form golden data (Task 0.9) with documented tolerances.
  5. CHANGELOG.md, docs/api/parity.md and AGENTS.md section 6 are updated as part of the work, not afterwards.
  6. Each phase ends with a "surfaces and docs" task; it is not optional.
  7. Warnings are errors; dead-code, unused and warning-suppression attributes are forbidden (AGENTS.md rule 10).
  8. Commits are directory-scoped: one directory per commit, feat(<scope>):/ref(<scope>): subject, and the completed tasks listed from hardest to easiest in the body (AGENTS.md section 2.1).

Parity map: Crystal-Builder module to phase ​

Crystal-Builder module (xtal/…)Phase
core/ elements, pyykko, lattice, site, structure, molecule, p1, supercell, slab, cellcut, transforms, neighbors, bonding, rings, groups (functional groups), measure, properties, scalars, describe, limits; io/text.py, io/cif_*, io/poscar.py, io/xyz.py1
core/ spacegroup, symmetry, subgroups; point-group part of core/molecule.py; analysis/kpath.py2
io/ all other formats, io/registry.py, io/export.py, io/atomic.py, io/project.py, io/trajectory.py, io/pmg.py; commands/; core/selection.py, core/tracking.py, core/atom_groups.py; workspace.py, params.py, plugins.py (registries); view/; STL part of modules/blender.py3
ff/ (all), core/prepare.py, commands/ff.py, commands/prepare.py, modules/{forcefield,scan,thermo,qha,dftb,orca,probe,process}.py, orca/4
analysis/ (except kpath), modules/{pxrd,zeopp,poregrid,report,registry,job,record,stub,net}.py, references.py5
build/, carbon/, graphene/, nanotube/, fullerene/, polymer/, mof/, modules/{build,carbon,graphene,nanotube,fullerene,polymer,mof}.py, commands/connections.py6
powder/, modules/powder.py7
agent/, cli.py (completed), ML calculators (ff/mace, ff/orb, ff/mattersim, ff/ase_engine.py)8
install.py, runtime.py, Blender rendering in modules/blender.py, xtalapp/out of scope (application packaging and GUI)

Known risks ​

  • moyo private APIs. Niggli, Delaunay and Minkowski reductions exist in moyo 0.22 but are crate-private. Plan: propose an upstream PR to export them and, until it is released, port the algorithms (MIT OR Apache-2.0 allows it, with attribution). Tasks 0.3 and 2.6.
  • Python-only dependencies with no Rust equivalent. Crystal-Builder uses gemmi (CIF, space groups), spglib, scipy (k-d trees, Voronoi, L-BFGS, sparse), ASE (band paths, trajectory reading, ML calculators), phonopy (phonons, thermodynamics), RDKit (SMILES, sketcher), rietx (indexing, Pawley, Rietveld). Each needs a Rust replacement or an explicit decision (Task 0.10).
  • Powder refinement. The numerical core lives in rietx, an external Python project with its own kernels (rietx-kernels). Phase 7 starts by studying it; its license must be verified before porting.
  • Data licensing. PORMAKE is MIT (verified). The RCSR database snapshots (analysis/data/RCSR*) and the Zeo++ radii need license checks before redistribution (Tasks 5.6.1, 5.2.2 and 6.11.1).
  • 500-line limit versus ported code. Many reference files exceed it (Python: core/prepare.py 1833, modules/powder.py 1893, mof/build.py 1784; sci-form: space_group_table.rs 6750, stereo.rs 1121, cell.rs 1048). Every port starts with a written split plan.
  • WASM limits. No threads by default, no filesystem, no subprocesses. The parity matrix records each justified exception.
  • Scope size. Phases 6 and 7 are larger than all the others combined. They are staged so each task group ships on its own.