Input writers

A writer turns one species and one job specification into the input files of one program. Writers fail closed: before rendering anything, a writer lists everything in the request it cannot express and, if the list is not empty, refuses with the reasons. It never guesses a keyword. The stance is the one vibe-qc’s QCSchema adapter takes, applied from the writing side.

For submission, run records, resource mapping and result retrieval, see calculation runs. Preparing an input and executing it are separate operations.

The writers

vibe-sketcher writers

Writer

Writes

Tasks

xyz

Cartesian geometry in angstrom. Charge and multiplicity go into the comment line as charge=0 multiplicity=1, the extended XYZ convention.

geometry

qcschema-molecule

A QCSchema molecule, schema version 2: geometry in bohr (CODATA 2018), charge, multiplicity. Only the fields vibe-qc’s adapter accepts.

geometry

orca

An ORCA 6 input (ORCA 5 reads it too).

sp, opt, freq, opt+freq, tddft, nmr

qcschema

A QCSchema input, schema version 1, exactly as vibe-qc’s adapter reads it: the molecule, the energy or hessian driver, model with method and basis, empty keywords.

sp, freq (HF)

vibeqc

A Python script that runs the job with vibe-qc’s run_job and writes QVF and Molden files; through vibe-scheduler, a QVF job container with the same translation.

sp, opt, freq, opt+freq, tddft

Every writer writes the first conformer of the species and refuses a species that has none; vibe-sketcher embed, POST /api/documents/{id}/embed, Generate 3D in the browser, or --embed on vibe-sketcher input make one. xyz and qcschema-molecule are geometry-only, so they refuse every calculation: asked for a B3LYP optimisation, xyz answers with one reason per thing it cannot carry, the task, the method, the basis and so on. qcschema refuses what vibe-qc’s QCSchema adapter would: an optimisation (an AtomicInput has no such driver), TDDFT, NMR, a Hessian for anything but HF, and every keyword, from dispersion to resources.

Discover capabilities and check a request

vibe-sketcher writers --json, GET /api/writers and MCP list_writers report writer names, tasks and specification fields. A listed field means the writer supports some uses of it; it is not a promise that every value or combination is supported. For example, ORCA supports frequency calculations and coupled-cluster methods, but this writer refuses that combination.

In the SDK, inspect a request before producing files:

from vibesketch.document import JobSpec, load
from vibesketch.inputs import get_writer

document = load("ethanol.vsk")
species = document.species[0]
spec = JobSpec(task="sp", method="B3LYP", basis="def2-SVP")
reasons = get_writer("vibeqc").refusals(species, spec)
for reason in reasons:
    print(reason)

This does not embed a geometry, write a file or submit a calculation. write_input runs the checks again before rendering. An empty refusal list means this writer can express the request; it does not check an installed calculation program, available compute resources or eventual convergence.

QCSchema input writing checks its supported tasks and fields but does not look up every method or basis name against an installed engine. The generated model lowercases those names; the receiving program remains responsible for accepting them. Use the dedicated vibeqc or orca writer when you need its program-specific translation and option checks.

Coordinates and units

Representation

Coordinate layout

Length unit

VSK conformer.xyz_angstrom

One [x, y, z] row per atom

Angstrom

XYZ input

One symbol and three coordinates per atom

Angstrom

ORCA * xyz block

One symbol and three coordinates per atom

Angstrom

Generated vibe-qc script

GEOMETRY rows converted before constructing atoms

Angstrom in the list; bohr passed to vibe-qc

QCSchema geometry

Flat array: x0, y0, z0, x1, y1, z1, ...

Bohr

The conversion uses BOHR_TO_ANGSTROM = 0.529177210903 from vibesketch.units, the CODATA 2018 value used by this implementation. Do not copy the same numeric array between angstrom and bohr fields without conversion. Constraint distances use angstrom and constraint angles/dihedrals use degrees. The 2D canvas coordinates are drawing coordinates, not a calculated 3D geometry.

vibe-qc

The vibeqc writer emits a script in the style of vibe-viewer’s vibe-qc templates: the geometry in angstrom converted to bohr with the CODATA 2018 factor, one Molecule with the charge and multiplicity (run_job takes neither), and one run_job call with QVF and Molden output:

vibe-sketcher input claisen.vsk --species m3 --program vibeqc --task opt+freq --method B3LYP --dispersion D3BJ --basis def2-SVP --approximation RIJCOSX --solvent CPCM:ethanol --nprocs 4 --embed

The translation follows what vibe-qc’s run_job accepts, and refuses past that:

Field

vibe-qc

method

HF as rhf or uhf; a functional as rks or uks with functional= (LDA, PBE, PBEsol, BLYP, B3LYP, PBE0, BHandHLYP, TPSS, revTPSS, TPSSh, M06-L, M06-2X, SCAN, r2SCAN, r2SCAN0, MN15, ωB97, ωB97X, ωB97X-D, ωB97X-V, ωB97M-V, HSE06, CAM-B3LYP, LC-ωPBE); the 3c composites, double hybrids, MP2, CCSD, CCSD(T) and DLPNO as methods. Never method="auto", which runs FCI or selected CI on small molecules. ωB97X-D3 is not in vibe-qc and is refused, not swapped for ωB97X-D.

basis

The basis sets vibe-qc ships: Pople, def2 (and def2-m), Dunning with aug- and core-valence, Jensen pc and pcseg, x2c-TZVPall, LANL2DZ, dhf.

approximation

RIJCOSX as density_fit=True, cosx=True, RI-J as density_fit=True, for HF and DFT. vibe-qc picks the fitting basis for the orbital basis; aux_basis may only name one of its fitting sets, such as def2-tzvp-jk.

dispersion

D3(BJ) or D4 on a functional (D4 needs vibe-qc’s optional dftd4).

solvent

CPCM with vibe-qc’s presets; vibe-qc has no SMD.

task

optimize=True; frequencies as hessian=True, a finite-difference Hessian on HF and DFT only; TDDFT as tddft=True, tddft_type="casida". vibe-qc computes no NMR shieldings.

constraints

Positions only, as geom_freeze.

resources

nprocs as num_threads; memory per core is refused, as vibe-qc takes a total budget.

QVF job containers

vibe-sketcher submit --program vibeqc does not send the script. It sends a QVF job container (QVF spec § 5.9), the file vibeqc run job.qvf executes and updates in place, so the result keeps the sketch that asked for it:

  • one structure, the species’ first conformer with its identity;

  • one job.spec in the names run_job takes: method (rks, uhf, ccsd(t) …), functional (JSON null for a method that takes none, left out where the method brings its own), basis, charge, multiplicity and vibe-qc’s tasks (single_point, optimize, hessian), with every other keyword of the table above under options by its run_job name (dispersion, density_fit, cosx, aux_basis, solvent, tddft, tddft_n_states, tddft_type, geom_freeze, num_threads). The dispersion, solvation and resources are stated as typed fields too, for any reader; the runner acts on options and refuses a keyword it does not know rather than dropping it;

  • the whole document in the x_vibesketch.document vendor section, with a preview of the scheme;

  • provenance.run_status: "pending".

The same writer translates both, so a container refuses exactly what the script refuses. vibe-scheduler runs the container on the venv program registered for vibe-qc (vibeqc, or the one program whose import probe is vibeqc) and needs a pin of that runtime’s git identity; when no container can be built or pinned (no qvf-writer, no such program, an older vibe-scheduler), the run script goes instead and the reason is reported (fallbacks over REST and MCP, standard error on the command line). --script asks for the script outright.

A finished container opens back in vibe-sketcher (vibe-sketcher info, vibe-sketcher serve, POST /api/documents, the open_document tool) with the drawing, the result’s geometry as a new conformer of the job’s species (method vibeqc:<tasks>) and the energy, provenance.scf_energy; saving it goes to a new file, since the container is a result. ORCA writes no QVF: its run records the queue’s directory, where its output is, for the result reading of a later release.

Staged recipes

In the browser or desktop panel, open Staged workflows. Generate the required 3D structures first, select species or the whole reaction scheme, then Save baseline recipe. A new recipe ID is chosen without replacing an existing one. Review resolved stages shows the settings and refusal reasons from the same REST service used by the CLI, including accepted-parent geometry references. Saved recipes and campaign records travel in QVF.

To compile, choose a new absolute directory on the server, review the default runtime and any Per-stage runtimes, and explicitly acknowledge the selected MACE model licence if eligible. Blank overrides inherit defaults. Compute and validation time budgets are separate. Compile campaign writes the campaign and displays the vq campaign run command; it does not submit jobs. Run that command on the server with vibe-scheduler, then use Refresh campaign to inspect compute state, validation state and scientific acceptance separately. A failed node has an explicit retry action; it records the next attempt for the next controller pass and keeps earlier attempts. No successful process exit is presented as scientific acceptance. Missing companions and refused settings remain visible. Reopen or edit a document and review it again before compiling; model licence acknowledgement is not retained as a preselected checkbox. Expanded runtime and evidence sections stay open across property-report and recipe-review refreshes, preserving entered runtime values. A changed document still requires a fresh review and model licence acknowledgement. If the panel refreshes while an action is running, its completion or refusal updates the current panel and restores its controls. Campaign status from an earlier document revision is discarded.

A recipe chains stages per species; vibe-sketcher recipe DOC (GET /api/documents/{id}/recipes, the show_recipes MCP tool) reviews it: every stage, per species, as the keywords vibe-qc’s run_job would take, in vibe-qc’s names, so what a launch sends is read before it is sent. The publication baseline (vibe-sketcher recipe-set DOC --baseline, POST /api/documents/{id}/recipes/baseline, set_recipe) is the vibyverse manuscript’s workflow: the sketch’s ETKDG and MMFF94 preparation, a MACE-OFF23 medium optimisation (method="mace", mlip_options, the ASE optimiser, 0.02 eV/Å), a PBE/def2-SVP optimisation without dispersion (method="rks", conventional SCF with density_fit=False, cosx=False, the orca-defgrid3 grid, SCF tolerances 1e-12 and 1e-9, 0.005 eV/Å), a finite-difference Hessian on the same surface at the accepted geometry (0.005 bohr), and a DLPNO-CCSD(T)/cc-pVDZ single point (dlpno_thresholds="tight", frozen_core="chemical", triples_mode="t1", which in vibe-qc names a rotated-occupied compatibility correction, not an iterative local T1 algorithm). Each numerical stage starts from the accepted geometry of its predecessor, and the recipe says so explicitly.

A stage is refused, with the reason, rather than translated: a dispersion correction on the DFT or Hessian stage (vibe-qc’s molecular routes do not propagate one until vibe-qc #548), a functional vibe-qc’s XC table does not resolve, a basis set it does not ship, a DLPNO stage for an open-shell species. Recipe containers require vibe-qc 0.17.25 or newer. They carry dlpno_ccsd_options={"dlpno_thresholds": "tight", "triples_mode": "t1"} and frozen_core="chemical". The preset belongs inside the options record, not beside it. The result records the resolved triples algorithm. The legacy recipe spelling t0 is refused explicitly; vibe-qc calls T0 local, and Sketch does not silently translate the requested mode. A MACE model’s licence acknowledgement is listed as something the operator gives at launch and is never saved in a recipe.

Running a recipe as a vibe-scheduler campaign

vibe-sketcher campaign-compile DOC RECIPE --out DIR (SDK vibesketch.document.campaign.compile_campaign, POST /api/documents/{id}/recipes/{recipe}/campaigns, the compile_campaign MCP tool) writes a vq.campaign/1 campaign into a new, empty directory and records it on the recipe; vq campaign run DIR/campaign.json DIR/run, printed last, runs it with vibe-scheduler’s own controller, which owns submission, idempotency, attempts and verified artifacts. The generated command quotes paths for a POSIX shell, preserving spaces and shell metacharacters as literal directory names. Copy the complete command, including its quotes. Per species and numerical stage there are two nodes:

  • <species>-<stage>-run, a compute node: the stage’s pending QVF job container and the stage driver, which reads its starting coordinates from the prepared stage QVF or the parent’s start/acceptance.qvf, checks the start/geometry.json cache against that structure, and runs vibe-qc’s container runner ({python} -m vibeqc._cli run by default, --runner to change it). It refuses to start from a geometry that is missing, names other atoms or another order, charge, multiplicity or units, or does not belong to the accepted result it names; it never falls back to the sketch’s coordinates.

  • <species>-<stage>-check, a validate node: the validator reads the result container alone and accepts it only when the run converged and exited cleanly, the charge and multiplicity are the species’, an optimisation left a structure with the submitted atoms in order, a Hessian has no vibration below the recipe’s imaginary-mode threshold (smaller negative ones are accepted with a review note; only the 3N-6 vibrations count, 3N-5 for a linear molecule, the translations and rotations vibe-qc reports as zeros left out), and a DLPNO single point states a finite correlated total energy in hartree. This may come from root energies or the latest run’s hash-verified structured DLPNO event, bound to its matching job and executed input. Missing, ambiguous, nonconverged or conflicting correlated results are refused; the SCF reference energy is never substituted. It publishes accepted/ (acceptance.qvf, the byte-identical raw result.qvf, a verdict.json cache and, for an optimisation, a geometry.json cache), or fails, which blocks every stage that needs it. Rejected results retain assessment.qvf. The derivative preserves original sections and unknown members and adds the documented vibe-sketch.stage-acceptance/1 vendor member: raw-result SHA-256, species/stage/recipe verdict, charge/spin and the selected QVF structure section, member path and SHA-256. Before use, the selected structure must also match the byte-identical raw result. Raw computation bytes are unchanged.

A stage that starts from an earlier stage’s geometry takes that stage’s accepted artifact as its input, so vibe-scheduler binds it to the producer attempt and manifest it was verified from; a stage whose parent is not its geometry source also consumes the parent’s QVF acceptance as a prerequisite input (the DLPNO single point starts from DFT geometry and requires the Hessian’s acceptance). Its stage QVF records both parent artifact hashes. The two-Hessian comparison additionally requires the same accepted geometry binding. Every stage QVF carries the canonical reaction scheme and its species structures; other species are labelled prepared context, not results of that stage. The first numerical stage starts from the sketch’s prepared conformer, written into its sources. The stage scripts use the Python standard library only.

vibe-sketcher campaign-status DOC RECIPE CAMPAIGN (GET .../campaigns/{campaign}, campaign_status) shows each stage’s process state in vibe-scheduler’s journal, with its attempts and what each retried, and apart from it its scientific acceptance: accepted with the verdict, rejected, not run when the run itself failed, or pending. A failed attempt is retried only explicitly: vibe-sketcher campaign-retry DOC RECIPE CAMPAIGN NODE (POST .../campaigns/{campaign}/retry, retry_campaign_node) authorises the next attempt as a retry of the failed one, and the next vq campaign run sends it. A campaign is compiled into a new directory and never rewritten. A recipe with a MACE stage compiles only with --accept-model-license, the acknowledgement of an eligible operator, which goes into the compiled containers and is recorded on the campaign, never in the recipe. Following a campaign needs vibe-scheduler installed (the queue extra); compiling does not, but without it the campaign’s digest is not recorded and vq campaign validate checks it later.

Rendering a campaign’s stages

vibe-sketcher campaign-energies DOC RECIPE CAMPAIGN --stage STAGE reports reaction energies directly from a completed campaign’s accepted artifacts. Use a terminal DLPNO stage explicitly; every campaign check must have succeeded and accepted its result. The report checks source pins, Queue artifact manifests, producer attempts and accepted-parent bindings, current species/recipe identity, correlated-event hashes, reported program/version, job settings and actual algorithm/threshold compatibility. It never creates document submission runs or uses an SCF reference energy as the correlated total.

In Staged workflows, refresh the selected campaign, choose Campaign energy stage, and download JSON, CSV, Markdown, LaTeX, SVG or QVF. Optional reaction IDs and coefficient maps use the same balanced stoichiometry rules as ordinary result reports. Incomplete or rejected campaigns, stale inputs, missing event evidence and incompatible protocols are refused. Explicit review warnings remain in the reports and figures. These are electronic energies; missing thermochemistry is unavailable, never zero.

vibe-sketcher campaign-render DOC RECIPE CAMPAIGN --species ID --out DIR (SDK vibesketch.document.renders.render_stages, POST .../campaigns/{campaign}/renders, the render_campaign_stages MCP tool) draws one species’ start and every accepted stage in one orientation, from the campaign’s archived artifacts only. Each artifact is checked against the manifest digest vibe-scheduler’s journal records for its producing attempt, and each file against its manifest entry, before it is read; the start comes from the campaign’s pinned sources. A stage that was not accepted is listed and never drawn, and a Hessian or single point is recorded with its own verdict on the geometry it shares.

The start geometry is placed in its principal-axes frame, and every accepted geometry and every trajectory frame is superposed on it by the proper rotation that minimises the RMSD (Kabsch), never a reflection, so an optimiser’s rigid drift does not turn the molecule between figures. Each geometry becomes an archive of its own, <species>-<stage>.qvf, with its aligned trajectory when the result carries one, beside renders.json, which names for every figure the node, attempt, manifest digest and result digest it came from, and its RMSD to the start. The images are vibe-viewer’s, vibe-viewer capture per archive (--size WxH, --publication) and vibe-viewer animate --kind trajectory per trajectory, run with its fixed isometric camera; vibe-sketcher imports no rendering stack. Without vibe-viewer the archives and the record are written and the warning gives the vibe-viewer batch command; --no-images writes them only.

ORCA

The ORCA writer translates the specification through a keyword table (vibesketch.inputs.orca_keywords) and refuses whatever the table does not cover, with the reason:

Field

What the table knows

method

HF; BP86, BLYP, PBE, revPBE, TPSS, SCAN, r2SCAN; B3LYP, B3PW91, PBE0, TPSSh, TPSS0, M06, M06-2X, BHandHLYP, X3LYP, CAM-B3LYP, ωB97X, LC-BLYP, r2SCAN0, PW6B95; with their own dispersion B97-D3, ωB97X-D3, ωB97X-D4, ωB97M-D4, ωB97X-V, ωB97M-V; double hybrids B2PLYP, DSD-PBEP86, PWPB95; the composites HF-3c, PBEh-3c, B97-3c, r2SCAN-3c, ωB97X-3c; MP2, RI-MP2, CCSD, CCSD(T), DLPNO-CCSD, DLPNO-CCSD(T). Write ω as w: wB97X-D3.

basis

The def2 (and ma-def2), Pople, Dunning (cc-pVXZ, aug-, core-valence), Jensen (pc, pcseg, pcSseg, pcJ) and x2c families.

aux_basis

def2/J, SARC/J, x2c/J; def2/JK, cc-pVXZ/JK; def2-SVP/C to def2-QZVPP/C, cc-pVXZ/C; AutoAux.

approximation

RIJCOSX and RIJONX (with a /J basis), RIJK (with a /JK basis).

dispersion

D2, D3ZERO (or D3), D3BJ (or D3(BJ)), D4.

solvent

CPCM or SMD, in water, methanol, ethanol, acetonitrile, acetone, DMSO, DMF, THF, dichloromethane, chloroform, toluene, benzene, hexane, cyclohexane, diethyl ether, pyridine, ammonia, octanol, ethyl acetate, carbon tetrachloride or 1,4-dioxane.

Beyond unknown names, it refuses what ORCA would not run as asked:

  • Composites: a basis set, auxiliary basis or approximation with a composite, which brings its own.

  • Dispersion: a dispersion correction for a method that has one built in, or for MP2 and coupled cluster.

  • Auxiliary bases: an approximation without the auxiliary basis set it needs, or with one it cannot use. RI-MP2 and DLPNO need a /C basis; with an approximation they need two auxiliary bases, more than the specification holds.

  • Tasks the method cannot do:

    • an optimisation with coupled cluster

    • frequencies where ORCA has no analytic Hessian: double hybrids, VV10 functionals, MP2, coupled cluster

    • TDDFT with MP2 or coupled cluster

    • NMR with coupled cluster

  • Bad inputs: a constraint naming an atom the species does not have, and a species with no electrons (H⁺).

The input follows the house style of the qc-input-library ORCA inputs:

  • Keyword line first: reference (UKS or UHF, spelt out for open shells), method, dispersion, basis, auxiliary basis, approximation, TightSCF, the task keywords, then CPCM(solvent).

  • Comments: the formula, method, basis and purpose, then the species and the geometry’s origin.

  • Blocks: %maxcore and %pal when the job names resources, then the %cpcm SMD block, %tddft (full TDDFT, tda false) and %geom constraints.

  • Geometry: angstrom with ten aligned decimals; no blank lines.

SMD is written as CPCM(solvent) with %cpcm smd true SMDsolvent "..." end, the form ORCA 5 and 6 both read. The file is named <species>_<method>_<basis>[_<options>].inp by the library’s naming rules, for example m1_b3lyp_def2-tzvp_cpcm-water_d3bj_freq_opt_rijcosx.inp.

! B3LYP D3BJ def2-TZVP def2/J RIJCOSX TightSCF Opt Freq CPCM(water)
# H2O / B3LYP / def2-TZVP — optimisation, then harmonic frequencies
# m1: water; vibe-sketch 0.1.0, geometry: etkdg+mmff94
%maxcore 3000
%pal nprocs 4 end
* xyz 0 1
O   0.0000000000   0.0000000000   0.1173000000
H   0.0000000000   0.7572000000  -0.4692000000
H   0.0000000000  -0.7572000000  -0.4692000000
*

Writing an input

From the command line, name a job of the document, or a species and a writer:

vibe-sketcher input scheme.vsk --job j1
vibe-sketcher input scheme.vsk --species m1 --program qcschema-molecule --output-dir inputs

With a species and a writer, the specification comes from options, or whole from --spec as JSON; --embed makes the 3D structure first when the species has none:

vibe-sketcher input scheme.vsk --species m3 --program orca --task opt+freq --method B3LYP --dispersion D3BJ --basis def2-SVP --aux-basis def2/J --approximation RIJCOSX --solvent SMD:ethanol --nprocs 4 --maxcore 2000 --embed

--species repeats, and --all takes every species of the document; both write into --output-dir. A species the writer refuses, such as the proton in a mechanism, is reported and the others are still written; the exit status is 3 if any was refused:

vibe-sketcher input claisen.vsk --all --program orca --task opt+freq --method r2SCAN-3c --embed --output-dir inputs

Without --output-dir the files go to standard output. A refusal prints the reasons and exits with status 3; an unknown job, species or writer is a usage error with status 2.

From Python:

from vibesketch.document import load
from vibesketch.inputs import WriterRefusal, write_input

document = load("scheme.vsk")
try:
    bundle = write_input(document, job="j1")
except WriterRefusal as refusal:
    print(refusal.reasons)
else:
    for file in bundle.files:
        print(file.name, file.media_type)

POST /api/documents/{id}/inputs writes one program’s input for several species of a stored document (species, default all) with one spec, as JSON or, with "format": "zip", as one archive with REFUSED.txt listing what was refused. The browser’s Inputs section uses it.

Over REST, POST /api/inputs takes the document and either job, or species and program with an optional spec; "embed": true makes the 3D structure first when the species has none, without storing it. It answers with the files, or with status 422 and {"detail": {"program": ..., "reasons": [...]}} when the writer refuses, and writes nothing.

Reaction paths (NEB)

A reaction drawn as reactants, an arrow and products can become the input of a nudged elastic band between them: ORCA’s NEB-TS (a climbing-image band, then a transition-state optimisation from its highest image), NEB-CI or plain NEB, and vibe-qc’s run_neb with or without the climbing image. vibe-qc has no transition-state refinement after the band, so it refuses neb-ts and says so.

Both ends of a band must list the same atoms in the same order, so every reactant atom is first paired with a product atom of the same element. The pairing changes the fewest bonds: each bond formed or broken counts one, and each hydrogen that moves counts two. All the cheapest pairings are found. When they differ only by the molecules’ symmetry, they are the same reaction. When they describe different reactions (which oxygen leaves in an esterification, a [3,3] or a [1,3] shift in a Claisen rearrangement), the mapping is ambiguous and nothing is written until you pin atoms.

Show the mapping before writing:

vibe-sketcher neb scheme.vsk --reaction r1 --show
r1: m1 + m2 -> m3 (charge 0, multiplicity 1)
  atoms, reactant -> product (hydrogens follow their atoms):
    m1:C1 -> m3:C6
    ...
  bonds:
    double to single: m1:C1–m1:C2
    single to double: m1:C2–m1:C3
    double to single: m1:C3–m1:C4
    double to single: m2:C1–m2:C2
    formed: m1:C1–m2:C2
    formed: m1:C4–m2:C1
  ends built; they differ by 1.6 Å RMS

Atoms are named by species, element and their 1-based place in the species (its SMILES atoms, then its hydrogens). Pin a pairing with --pin reactant:atom=product:atom, repeated as needed; the esterification’s acyl-oxygen cleavage, for example, pins the acid’s hydroxyl oxygen to water:

vibe-sketcher neb ester.vsk --reaction r1 --pin m1:4=m4:1 --method PBE --basis def2-SVP --output-dir path

The two ends are built from the species’ structures as complexes. The bonds the reaction forms are held at 1.85 times the two covalent radii on the reactant side, and the bonds it breaks the same on the product side. An atom that gains one partner and loses another keeps them opposite, as in a substitution. The reactant side takes the product’s conformation where its own bonds allow, so a diene is drawn s-cis. The product end is turned onto the reactant end by a proper rotation, with interchangeable hydrogens paired by position. Both programs optimise the ends before the band (PreOpt_Ends true for ORCA; optimize_molecule in the vibe-qc script); --no-preopt leaves them as built. The geometries are starting points, not optimised structures.

vibe-sketcher neb scheme.vsk --reaction r1 --method B3LYP --basis def2-SVP --dispersion D3BJ --images 8 --output-dir path

ORCA gets <reaction>_<method>_<basis>_<kind>.inp and the product end as ..._product.xyz, which the %neb block names. The level of theory goes through the same keyword model and refusals as the ORCA writer: coupled cluster, for example, is refused, since a band needs gradients. vibe-qc gets a run script with both ends. It takes HF or a functional with one of vibe-qc’s basis sets; dispersion, solvation and integral approximations are not written into run_neb yet and are refused. The script evaluates one image at a time (n_jobs=1): vibe-qc’s parallel image workers cannot take a Molecule yet (mpei/vibe-qc#564), so nprocs above 1 is refused. Reagents drawn at the arrow are not part of the path. Each species takes part once per side, so 2 A -> B is refused as unbalanced. Two open-shell species on one side are refused, because the drawing does not fix the complex’s spin state.

The same is available from Python (vibesketch.inputs.neb.reaction_mapping and neb_inputs), over REST (POST /api/documents/{id}/reactions/{rid}/mapping and .../neb) and to agents (map_reaction, write_neb_inputs). The mapping report places every mapped atom on the canvas (reactant_at, product_at), marks the reaction centre (centre), and gives an ambiguous mapping’s equally cheap pairings with the pins that select each (choices).

In the browser, each reaction card has an Atom mapping and reaction path section:

  • Map atoms pairs the atoms and marks the reaction centre in orange on the canvas. Pointing at a row of the pair list marks that pair in blue.

  • An ambiguous mapping lists its equally cheap pairings, each with Use this pairing, which pins it.

  • To pin a pair yourself, select one reactant atom and one product atom on the canvas, then press Pin selected atoms. Pins show as chips; × removes one.

  • Write NEB inputs downloads the program’s files as a zip.

The marks are for display only: they are no edit and no undo step, and closing the section removes them.

JSON specifications and geometry persistence

--spec accepts the specification itself as JSON, not a path to a JSON file. Do not combine it with specification flags such as --task or --method. For example, with an embedded species:

vibe-sketcher input ethanol.vsk --all --program vibeqc \
  --spec '{"task":"sp","method":"B3LYP","basis":"def2-SVP"}' \
  --output-dir inputs

For a saved specification in a POSIX shell, use --spec "$(cat spec.json)". The SDK takes a JobSpec; REST and MCP take a JSON object in spec, rather than a string containing serialized JSON.

Geometry generation differs by entry point:

Entry point

Missing geometry

Where it is retained

SDK write_input / write_inputs

Refused; call embed first

In the returned embedded document, when you retain and save it

CLI input --embed

Generated for selected species

Only for that input-generation call; use embed separately to save it

REST POST /api/inputs with embed: true

Generated for the posted document

Only for that request

REST POST /api/documents/{id}/inputs

Refused; call the document’s /embed route first

/embed updates the shared document

Browser Write inputs

Generated first

In the shared document; save the document to persist it to disk

MCP write_inputs

Generated by default; embed: false disables this

In the shared document; save it separately

Single-species writers use the first conformer. Requesting several conformers does not create a calculation for each one. Writing species inputs does not itself compute a reaction energy or path; use the explicit result-analysis and NEB workflows.

Freeze an atom during optimisation

Constraints refer to zero-based positions in the species’ first conformer, not canvas labels or compound numbers. Export XYZ and inspect its atom rows before choosing indices; the first atom row after the two header lines is index 0. Recheck indices if you change the molecular structure or replace its geometry.

For example, after preparing ethanol.vsk with a 3D conformer, freeze its first atom while requesting a vibe-qc optimisation:

vibe-sketcher input ethanol.vsk --all --program vibeqc \
  --spec '{"task":"opt","method":"B3LYP","basis":"def2-SVP","constraints":[{"kind":"position","atoms":[0]}]}' \
  --output-dir frozen-inputs

A position constraint has one atom and no value. Distance, angle and dihedral constraints name two, three and four distinct atoms respectively; their optional value fixes a target rather than the starting value. They are supported by the ORCA writer, while the vibe-qc writer supports positions only. Constraints apply to opt or opt+freq, not single points. These are calculation-input constraints; they do not constrain Clean up or Generate 3D in the drawing UI.

Adding a writer

Subclass vibesketch.inputs.InputWriter, declare the name, the tasks and the specification fields it can express, and implement _refusals (the writer-specific reasons to refuse) and _render (the files). The base class’s write is the only public entry point: it checks the task and every specification field against what the writer declared, adds the writer’s own reasons, and only calls _render when there is nothing to refuse. vibesketch.inputs.register adds the writer to the registry in the current Python process. SDK calls and REST routes in that process use the same registry. Registering in an interactive Python session does not install a plugin into a separately started vibe-sketch process. Register the writer in the application’s startup path before invoking its CLI or serving its API; there is no automatic entry-point plugin discovery in the current registry.

The browser’s program selector and queue submission support are separate: registering a writer does not add a browser option or teach the queue how to execute a new program. Add documentation, refusal tests and appropriate interface integration when extending the supported writer set.

Explicit restricted CC reference in staged recipes

The default dlpno.reference_contract is all_tested_channels. An operator may explicitly select real_restricted_cc for a closed-shell DLPNO single point, for example recipe-set document.vsk --baseline --all --reference-contract real_restricted_cc. The SDK’s baseline_recipe, REST baseline request, MCP set_recipe and browser CC reference contract selector use the same field. Full recipe JSON stores it under the DLPNO options; it is not an optimization or Hessian option.

This requires a selected vibe-qc interpreter with the explicit contract API. Unknown runtimes and custom wrappers are refused before execution. Acceptance requires converged SCF, verified internal stability, resolved internal and external real stability channels with finite eigenvalues, and the actual correlated run input and total. External RHF-to-UHF instability remains usable=false; reference_usable is recorded separately. Both channel states, eigenvalues and the selected contract remain in QVF verdicts and reaction-table source records. A manual review cannot override missing channels in this path. PBE optimization and Hessian acceptance are unchanged.

This contract does not establish complex-orbital stability, global minima, transition states or external correlated accuracy. Availability of the adapter alone does not constitute scientific qualification of a runtime.

Hessian displacement compatibility

A staged Hessian sends its exact displacement_bohr as the QVF job option hessian_step_bohr. Both 0.005 and 0.0025 bohr can be requested in separate saved stages on the same DFT geometry. A runtime without this option must refuse the job; the displacement is never replaced by its default. Acceptance requires the result QVF vibration metadata to record the requested surface.step_bohr and surface.stencil = "central". Missing or mismatched records fail acceptance and block dependent stages. This interface check is not numerical qualification of either Hessian.

Digital Discovery numerical profile

The standard baseline retains its original settings. Select Digital Discovery exact protocol under Staged workflows → Numerical protocol to save the paper’s separate recipe. Select Real restricted CC explicitly when that is the intended reference contract; it is never inferred. Review resolved stages before compiling. In the SDK use baseline_recipe(species, profile="dd", reference_contract="real_restricted_cc"); in the CLI:

vibe-sketcher recipe-set reaction.vsk --baseline --scheme --profile dd --reference-contract real_restricted_cc
vibe-sketcher recipe reaction.vsk --json

REST /recipes/baseline and MCP set_recipe accept profile: "dd" with the same reference-contract choice. It requests MACE-OFF23 medium CPU/float64, 0.005 eV/Å and 200 steps; PBE/def2-SVP without dispersion, density fitting or COSX, fine grid, 0.001 eV/Å and 300 steps. Both surfaces use explicit SCF energy/gradient tolerances 1e-12/1e-9 and 200 SCF/stability iterations. Two Hessian stages use the accepted DFT geometry and 0.005/0.0025-bohr central steps, require positive projected modes, and compare spectra within 5 cm⁻¹. This is five numerical queue jobs per species (the two stencils are separate jobs), plus their validation nodes. A missing comparison record refuses acceptance; it cannot be replaced by a completed queue process.

The endpoint is chemical-frozen-core TightPNO DLPNO-CCSD(T)/cc-pVDZ with cc-pVDZ-RIFIT, RHF settings as above, 150 CC iterations, CC energy/residual tolerances 1e-10/1e-8 and t1 (rotated-occupied compatibility correction, not iterative local T1). Inspect and archive the runtime’s resolved numeric PNO thresholds and core count, not just the preset name. The recipe requires vibe-qc >=0.18,<0.19 with the requested capabilities; no patch is pinned. A version string does not prove a released build: the campaign owner must also record verified package/source/native identities and the model hash. Existing running environments must remain unchanged. This preset and its software tests do not qualify the numerical remedy or authorize a paper replay.