Periodic-method requirements from basissetdev¶
Audience: the periodic-methods main development chat.
Authors: basissetdev, M. F. Peintinger.
Date: 2026-05-08; last refresh 2026-05-13.
Status: living document; rebased onto main as features land.
2026-05-13 refresh. Since the initial audit on
2c7c7df, Codex landed the native GDF backend (periodic_rhf_gdf.py,periodic_k_gdf.py,periodic_gdf_blocks.py), replacing the retired in-process PySCF periodic backend, which CLAUDE.md § 10 now formally forbids. CRYSTAL-style FMIXING (previous-Fock mixing) and Fermi-Dirac smearing are wired through the GDF and Ewald multi-k paths. Shared SCF mixing helpers (validate_fraction_01,mix_fock_matrices) live incpp/include/vibeqc/scf_mixing.hpp, new basissetdev work must reuse these, never duplicate (manifest rule). See per-requirement status notes below.
This is the punch list of periodic capabilities basissetdev needs
in order to reproduce the published pob-paper test sets in vibe-qc.
The papers in scope are:
M. F. Peintinger, D. Vilela Oliveira, T. Bredow, J. Comput. Chem. 34, 451 (2013). [pob-TZVP, PT2013]
D. Vilela Oliveira, J. Laun, M. F. Peintinger, T. Bredow, J. Comput. Chem. 40, 2364 (2019). [pob-TZVP-rev2 + pob-DZVP-rev2, VO2019]
Together they enumerate roughly 70 binary and ternary ionic / semiconducting / TM-oxide / metallic systems plus a 9-compound subset of the X23 molecular crystals. Each requirement here is tagged with the table(s) it gates and the count of compounds that become runnable when it lands.
Conventions¶
P0: hard blocker for ≥10 compounds in the test set.
P1: blocker for 1-10 compounds, or for cross-method validation.
P2: nice-to-have / faithful reproduction of CRYSTAL workflow.
vibe-qc state originally audited on commit
2c7c7dfofbasissetdev; refreshed 2026-05-13 on commit1bf32cc.Feature counts below are conservative, orthorhombic is the most permissive cell shape vibe-qc currently handles.
Test-set overview¶
Source |
Table |
Cell shape |
Compounds |
Listed |
|---|---|---|---|---|
PT2013 |
T4 |
cubic |
12 |
LiCl, NaCl, LiF, NaF, KF, CaF₂, K₂O, MgO, CaO, LiH, NaH, KH |
PT2013 |
T5 |
hexagonal |
10 |
BeF₂, ScCl₃, MgBr₂, BeO, α-SiO₂, B₂O₃, Al₂O₃, NaNO₃, MgCO₃, FePO₄ |
PT2013 |
T6 |
orthorhombic |
5 |
BeBr₂, NaNO₂, CaH₂, CrCl₂, GeSe |
PT2013 |
T8 |
cubic semiconductor |
22 |
C(diamond), Si, Ge, AlP, AlN, Na₂Se, GaAs, GaP, ZnS, MnSe, ZnSe, β-BN, β-SiC, TiC, Cu₃N, VC, VN, TiN, CrN, K₂S, MnS |
PT2013 |
T9 |
hexagonal semicond. |
9 |
NiAs, α-SiC, α-BN, B₄C, ScB₂, CoS, CuS, GaF₃, GeO₂ |
PT2013 |
T10 |
cubic TM oxide |
7 |
Sc₂O₃, MnO, FeO, CoO, NiO, Cu₂O, ZnCr₂O₄ |
PT2013 |
T11 |
hexagonal/tetragonal TM oxide |
4 |
V₂O₃, Cr₂O₃, ZnO, TiO₂(rutile) |
PT2013 |
T12 |
cubic metal |
11 |
Li, Na, K, Ca, Sc, V, Cr, Fe, Ni, Cu, Al, Ni₃Al |
PT2013 |
T14 |
HF cubic ionic |
12 (subset of T4 + K₂S) |
LiCl, NaCl, LiF, NaF, KF, CaF₂, K₂O, MgO, CaO, LiH, NaH, KH |
VO2019 |
T2 |
cubic ionic |
14 |
+ KBr, SiF₄ |
VO2019 |
T3 |
hexagonal ionic |
10 |
(overlap with PT2013 T5) |
VO2019 |
T4 |
orthorhombic ionic |
4 |
NaNO₂, CaH₂, CrCl₂, GeSe |
VO2019 |
T6 |
cubic semicond. |
14 |
(subset of PT2013 T8) |
VO2019 |
T7 |
hex semicond. |
9 |
(subset of PT2013 T9) |
VO2019 |
T9 |
cubic TM oxide |
7 |
(overlap with PT2013 T10) |
VO2019 |
T10 |
hex/tet TM oxide |
5 |
+ TiO₂(anatase) |
VO2019 |
T14 |
molecular crystal |
9 |
from X23, dispersion-dominated |
VO2019 |
Figs 2-7 |
molecular hydride dimer |
~30 |
H_n A-AH_n at 1.4-5 Å, A=Li-Br |
Total unique compounds: ≈75. Counted by cell shape: roughly 40 cubic, 20 hexagonal, 10 orthorhombic/tetragonal, plus the molecular-crystal subset.
Hard requirements¶
R1, Non-orthorhombic Ewald [P0]¶
The current ewald_j / periodic_*_ewald family rejects any cell
that is not strictly orthorhombic, because the FFT Poisson solver
indexes the real-space grid by Cartesian (a×b×c) box dimensions.
Hexagonal, trigonal, and tetragonal cells with non-orthogonal a/b
or a/c are refused at SCF entry with:
“system lattice must be orthorhombic (FFT Poisson solver does not yet support triclinic cells).”
The test-set fraction that requires non-orthorhombic Ewald:
Hexagonal: PT2013 T5 (10), PT2013 T9 (9), PT2013 T11 (3), VO2019 T3 (10), VO2019 T7 (9), VO2019 T10 (4), ≈32 unique compounds blocked.
Tetragonal: TiO₂(rutile), TiO₂(anatase), 2 compounds.
Acceptance: run_rhf_periodic_multi_k_ewald3d accepts
hexagonal (a, b=a, c, α=β=90°, γ=120°) cells; total energy on
α-Al₂O₃ (R-3c) at experimental geometry agrees with PySCF.pbc.GDF
to 100 µHa per formula unit. Tetragonal (P4/mmm and P4₂/mnm
spacegroups) covered by the same fix.
Note for kpoints.py: the hexagonal/trigonal Γ-centring guard
is already in place; the work is on the Poisson side. No changes to
the k-mesh API required.
R2, Multi-k MP-grid SCF on production basis sizes [P0]¶
Status as of 2026-05-13: partially landed.
Native GDF backend live: periodic_rhf_gdf.py (Γ-only),
periodic_k_gdf.py (multi-k), periodic_gdf_blocks.py (Bloch
assembly from lattice blocks). The in-process PySCF periodic
backend was retired (commits 545db04 / 7ab9384), manifest
§ 10 now forbids importing PySCF inside vibe-qc; parity testing
against PySCF happens out-of-process via examples/regression/ runner_pyscf.py. The CaF₂ pob-TZVP RKS-PBE CRYSTAL14 regression
fixture (e46211c) is the first cubic-ionic parity test
exercising basissetdev’s .d12 sidecar pipeline (Phase 14h).
Already landed in the multi-k path:
smearing_temperatureFermi-Dirac occupations (periodic_rhf_multi_k_ewald.pylines 33-34, 156, 445;periodic_k_gdf.pyline 76). Unit-bearing strings (“0.01 Ha”, “300 K”) accepted via the GDF gamma path (7eacfd3). Free energy withE - T·Scorrection surfaced in the result bundle (periodic_rhf_gdf.pyline 548).fock_mixing(CRYSTAL FMIXING-equivalent) wired through both Γ-GDF and multi-k. Validation against MgO PBE/POB-TZVP CRYSTAL14 totals viaexamples/regression(commit7c02666).Low-dimensional MP meshes (1D / 2D systems) accepted by the legacy path (
f4d95f9).Periodic dimensionality is logged in GDF jobs (
56fd2e7).
Still open:
Validation against CRYSTAL k-mesh density at production sizes. PT2013 / VO2019 use Pack-Monkhorst grids around 8×8×8 for rocksalt ionics, 4×4×4 for the larger sesquioxides. vibe-qc tests have so far focused on small (2×2×2 to 4×4×4) grids; the linear-system size at full pob-TZVP × 8×8×8 is unmeasured. The Phase-14h
.d12sidecars now make this measurable: same compound, same basis, same k-mesh, on both codes viavq. Bench needed.Smoke test on metallic Cu (FCC, T12). Smearing is in; the metal-specific SCF flow at production size hasn’t been benchmarked. T12 metals (Li, Na, K, Ca, Sc, V, Cr, Fe, Ni, Cu, Al, Ni₃Al) inherit any remaining issues.
Acceptance: MgO total energy at Γ + 8×8×8 Pack-Monkhorst with pob-TZVP/PW1PW agrees with PT2013 SI Table 1 (E = −275.477 595 Ha per cell) to 1 mHa. Metallic Cu (FCC) converges with smearing σ = 0.01 Ha and reproduces the 2013 Table 12 lattice constant (3.506 Å) to 0.01 Å.
Reuse, don’t duplicate. Shared mixing helpers
(validate_fraction_01, mix_fock_matrices) in
cpp/include/vibeqc/scf_mixing.hpp are the canonical
implementation across molecular + periodic, per manifest § 10.
Any new basissetdev SCF-control work plugs into this header.
R3, Stable open-shell UKS / UHF for transition-metal oxides [P0]¶
Status as of 2026-05-13: still blocked. No change since the
2026-05-08 audit; the broken-symmetry initial guess for AFM
ground states has not landed. Basissetdev’s Goal 3 ships the 6
AFM-II compounds (MnO, FeO, CoO, NiO, α-MnS, α-MnSe) as
BLOCKED ON: R3 stubs, their .py inputs are wired so the
moment R3 lands, only the initial-guess hook needs filling in.
The .d12 sidecars (Phase 14h) skip emission for AFM compounds
since the CRYSTAL ATOMSPIN block requires the same magnetic-
ordering decision; both emit when R3 + ATOMSPIN-aware generator
support land together.
The multi-k UKS (periodic_uks_multi_k_ewald.py) and UHF
(periodic_uhf_multi_k_ewald.py) modules exist. The blocker is
not the kernel but the initial-guess strategy for
antiferromagnetic ordering. Currently both default to Hcore →
identical α/β densities → SCF converges to the closed-shell
solution by symmetry. This is the wrong basin for AFM systems.
Compounds blocked (counted once across PT2013 + VO2019): MnO, FeO, CoO, NiO (T10/T9), Cr₂O₃, V₂O₃ (T11/T10), CrCl₂ (T6/T4), CrN, MnS, MnSe (T8/T6), 10 transition-metal compounds.
Acceptance: broken-symmetry initial guess (Mulliken-localised single-atom UKS densities tiled into the AFM unit cell, optionally with a small spin-symmetry-breaking field on the magnetic sublattice). NiO total energy with pob-TZVP/PW1PW reproduces PT2013 SI Table 1 (−3167.495 768 Ha per cell, two formula units in the AFM-II unit cell) to 1 mHa.
R4, PW1PW hybrid functional [P0]¶
PW1PW is the workhorse functional for PT2013 and VO2019. It is the 1-parameter global hybrid of Bredow & Gerson (T. Bredow, A. R. Gerson, Phys. Rev. B 61, 5194 (2000), DOI 10.1103/PhysRevB.61.5194), originally introduced as the “HF+PWGGA hybrid approach” in §III.D of that paper. The mixing α = 0.20 was empirically optimised on MgO / NiO / CoO bulk properties and coincidentally matched the B3LYP exchange-mixing fraction. The “PW1PW” name came into use in subsequent CRYSTAL-community papers (Peintinger 2013 onward).
Definition:
E_x = 0.20 · E_x^HF + 0.80 · E_x^PW91E_c = E_c^PW91
Where PW91 = Perdew-Wang 91 GGA (libxc IDs XC_GGA_X_PW91 = 109
and XC_GGA_C_PW91 = 134). The hf_exchange_fraction mechanism
in periodic_rks_multi_k_ewald.py already supports α = 0.20
mixing; what’s missing is the named entry in vibe-qc’s functional
registry that resolves "PW1PW" to this triplet. Status
2026-05-13: still missing, no registry alias landed since the
audit. The 33 .d12 parity sidecars in Phase 14h currently emit
the no-DFT (HF) form; once PW1PW resolves, the generator just
flips method="pw1pw" and CRYSTAL’s PW1PW keyword does the
matching parity run.
Note: PW1PW is distinct from PBE0 (PBE-based hybrid, α = 0.25), B3LYP (three-parameter Becke88 + LYP + VWN5), and plain PW91 (no HF mixing). Do not silently substitute any of these for PW1PW in benchmarks against the pob SI tables.
Acceptance: functional="PW1PW" resolves to the Bredow-Gerson
hybrid with α = 0.20 and PWGGA (X + C) DFT components. RKS total
energy on MgO with pob-TZVP at converged k-mesh equals PT2013 SI
Table 1 (E = −275.477 595 Ha per cell) to 1 mHa. (Without R1+R2
this is testable only for cubic ionics and TM oxides.)
The Bredow-Gerson 2000 paper additionally benchmarks HF+LYP, HF
alone, B3LYP, BLYP, PBE, and plain PWGGA on MgO / NiO / CoO. If
the periodic chat wants a smaller cross-validation acceptance
target, the seven-functional comparison from that paper’s
Tables I-IV is a clean test fixture: ≈30 (compound × functional)
data points at known geometry. PDF reference:
/private/tmp/bredow2000.pdf on the user’s machine; user-shipped
2026-05-08.
R5, Geometry optimisation in periodic [P0]¶
Status as of 2026-05-13: still blocked. Gradients are
present and have been extended (RKS gradients,
periodic_gradient_rks.py; open-shell gradients,
periodic_gradient_open_shell.py; multi-k gradients,
periodic_gradient_multi_k.py), but no atom-or-lattice
relaxation driver. Phase 14h .d12 sidecars fix the lattice at
the experimental value so the parity test isn’t also gated on
this requirement.
The molecular path has _optimize_geometry (runner.py); the
periodic path has gradients (periodic_gradient*.py) but no
relaxation driver. Every line of every pob-paper table is a
relaxed geometry: lattice parameters and atomic positions are
optimised against the basis. Without relaxation, comparison to
the paper tables is impossible.
Two flavours needed:
Atomic-position-only relax at fixed lattice. Required for T5/T6/T9/T10/T11/T8 (anything with internal coordinates), ≈40 compounds.
Lattice + atomic-position simultaneous relax. Required for every cell in the test set, ≈75 compounds.
Acceptance: wrap the existing periodic-gradient drivers behind an ASE BFGS / FIRE optimiser that updates both atomic positions and the lattice tensor. NaCl (Fm-3m) with pob-TZVP/PW1PW relaxes from 5.5 Å starting cell to 5.609 ± 0.005 Å (PT2013 Table 4), atomic positions stay at (0, 0, 0) and (½, ½, ½) by symmetry.
For the lattice-tensor side, the stress tensor is the natural primitive but is currently not in vibe-qc (memory: deferred to v0.8). A first cut can use finite-difference lattice gradient (perturb each lattice parameter by ε, recompute total energy, divide) and feed that to the BFGS optimiser. Slower than analytical stress but unblocks the test set.
R6, Counterpoise / BSSE for periodic crystals [P1]¶
VO2019’s central novelty is the BSSE-aware re-optimisation. They
use CRYSTAL’s ATOMBSSE to compute the per-atom counterpoise
correction in a periodic crystal (ghost-atom basis on the heavy
atom, no nuclei, no electrons, in the otherwise-real lattice).
vibe-qc has no equivalent yet. To reproduce VO2019 numbers, needed; to use the rev2 basis sets, not strictly needed (the basis already incorporates the BSSE-aware exponent shift).
For Goal 4 of basissetdev (re-running the rev2 optimisation in
vibe-qc), counterpoise IS required as part of the objective
function. Hence P1 not P0.
Acceptance: ghost_atoms=[(symbol, position), …] parameter on
PeriodicSystem that places basis functions but no nuclei / no
electrons. NaH ATOMBSSE matches CRYSTAL within 1 mHa.
Cross-method validations¶
R7, Functional zoo: PBE, PBE0, B3LYP, BLYP, HSE [P1]¶
PT2013 and VO2019 cite cross-validation against B3LYP and PBE0 in side notes. vibe-qc’s libxc-based functional registry should already accept these strings (the runner advertises them). What’s missing is end-to-end verification at converged k-mesh + multi-k SCF for the cubic ionic subset (which is the easy 12-compound benchmark). Listing here so the periodic chat doesn’t deprioritise.
Acceptance: the 12 cubic ionics from PT2013 T4 run with PBE, PBE0, B3LYP, BLYP, HSE06 (each), in addition to PW1PW.
R8, Wu-Cohen GGA (WC) [P2]¶
WC (XC_GGA_X_WC = 118; correlation typically PBE) is used in
PT2013 for the metallic systems (preliminary basis-set
optimisation). Easy to add, libxc has it; the question is the
registry alias.
Acceptance: functional="WC" resolves to WC-X + PBE-C.
Numerics & screening¶
R9, TOLINTEG-equivalent screening control [P1]¶
linear_dependence.py and eigs_preflight.py already point at
LatticeSumOptions.schwarz_threshold as the TOLINTEG-equivalent
knob. PT2013 explicitly mentions ITOL5 = 27 (vs default 14) for
ionic SCF convergence, i.e. extremely tight Coulomb-tail screening.
Need to verify schwarz_threshold covers ITOL4 (Schwarz
two-electron) AND ITOL5 (penetration / overlap-based truncation
distance). If they’re conflated in vibe-qc, surface separately.
Acceptance: running the sulfide subset (ZnS, MnS, K₂S, CoS, CuS) with default screening converges; bumping the equivalent of ITOL5 to 27 closes any residual SCF oscillation.
R10, Atomic-reference HF energies for cohesive / atomization [P1]¶
PT2013 Table 13 reports atomization enthalpies. To compute these you need (a) the periodic total energy and (b) the isolated-atom total energy in the same basis. The molecular path handles (b) at the symmetry-broken UHF level; the question is exposing a single-atom reference path that accepts a Mulliken-style fractional- occupation specification (atoms in PT2013 are computed with “neutral atomic configurations from our website”, the .single files in the Bredow archive).
Acceptance: vq.atomic_reference_energy(symbol, basis, configuration="neutral") returns the SCF energy for the open-shell
atom with the published occupation, for every element in pob-TZVP.
Lower-priority polish¶
R11, D3(BJ) for periodic [P2]¶
dispersion.py exists in molecular path. VO2019 Table 14 applies
D3(BJ) on top of pob-TZVP / pob-TZVP-rev2 for the X23-subset
molecular crystals; the deltas drive ≈2-3 % lattice-constant
improvements. Periodic D3 is an additive post-SCF step on the
relaxed geometry, needs lattice summation of the C₆/C₈ pairs but
no SCF intrusion.
Acceptance: ZnO + D3(BJ) with pob-TZVP-rev2 reproduces VO2019
Table 14 D3-corrected c to 0.01 Å.
R12, ATOMBSSE for the molecular hydride dimers [P2]¶
The 2019 BSSE-correction recipe uses molecular counterpoise on H_n A-AH_n dimers (computed in ORCA 3.0 with MP2). vibe-qc’s molecular DF MP2 was wired in v0.7.3. A native vibe-qc version of this step is needed for Goal 4 (re-running the rev2 optimisation without external ORCA dependencies).
Acceptance: counterpoise(H₂O)₂ at 2.5 Å with vibe-qc/MP2 matches ORCA 3.0 MP2 to 1 mHa.
Basis-optimization gradient infrastructure¶
R13, Lattice-summed exponent/coefficient-derivative 3c/2c kernel [P1]¶
Status as of 2026-06-21: ask raised; not started. New requirement from the
periodic basis-optimization gradient effort (the crystal OPTBASIS analogue; see
PERIODIC_GRADIENT_DESIGN.md).
The periodic basis-parameter gradient assembles, per k-point,
dE/d(eta) = Sum_k w_k Re[ tr(P dHcore/d(eta)) + 1/2 tr(P dG/d(eta))
- tr(W dS/d(eta)) ].
The clean one-electron pieces dS(k)/d(eta) and dT(k)/d(eta) are done (Phase
P1) in Python, by Bloch-summing the molecular overlap_/kinetic_exponent_ derivative bindings between a home-cell shell and its image. The hard remaining
piece (Phase P2) is the two-electron Coulomb derivative dG(k)/d(eta) and the
nuclear derivative dV(k)/d(eta). Both are built from the lattice-summed
GDF/Ewald 3-index (P|mu nu) and 2-index (P|Q) integrals with the Ewald-3D gauge,
so their basis-parameter derivative needs the d/d(eta) sibling of the existing
d/dR gradient kernels compute_3c_eri_lattice_gradient_weighted /
compute_2c_eri_lattice_gradient_weighted (used today by
periodic_gdf_gradient.py for
nuclear gradients).
This is the one piece of the periodic basis-gradient that lives in the
periodic-SCF integral layer (cpp/), which basissetdev does not own, hence this
ask (CLAUDE.md s11). It is not a hard blocker: a first working basis-gradient
can use an integral-FD dG(k)/dV(k) behind the assembly’s provider with no C++
change. R13 enables the fully analytic, production route. Marked P1 (blocks
cross-method validation of the periodic optimizer), not P0.
Acceptance: a binding analogous to
compute_3c_eri_lattice_gradient_weighted that, given a target shell and a
primitive index (plus a coefficient variant), returns the weighted contraction
of the lattice-summed 3c/2c integral derivative w.r.t. that primitive’s exponent
(or coefficient). Validated to 1e-6 or better vs a central integral FD of the
Bloch-summed 3c/2c tensor at fixed k, on a small cell. Until it lands,
basissetdev proceeds with the integral-FD fallback behind the provider.
Out of scope here (other chats / future versions)¶
Periodic stress tensor. Memory: reserved for vibe-qc v0.8. Once landed, R5 lattice opt becomes analytical instead of FD.
Slab / surface support. Same: v0.8 deliverable.
AutoAux periodic aux basis. Owned by the DF dev chat (memory:
feedback_aux_basis_routing.md).CCM / cyclic-cluster method. Memory: deferred to a later vibe-qc version.
Suggested implementation order¶
The order that unblocks the most of the test set per landed feature:
R5 atomic-position relax + R4 PW1PW + R7 functional verification → unlocks 12 cubic ionics from PT2013 T4 + 12 cubic ionics from VO2019 T2 (overlap) + 22 cubic semiconductors from PT2013 T8 + 7 cubic TM oxides from PT2013 T10 = ≈40 compounds runnable.
R3 broken-symmetry UKS guess → unlocks the 10 TM oxide / chloride / nitride compounds.
R1 non-orthorhombic Ewald → unlocks the 32 hexagonal/ tetragonal compounds. Big single-feature payoff.
R5b lattice relax (FD lattice gradient) → enables the actual lattice-constant comparison vs. paper tables for everything above.
R2 metallic k-mesh smearing → unlocks the 12 cubic metals.
R6 ATOMBSSE periodic + R12 molecular counterpoise → unlocks the rev2 re-optimisation pipeline for Goal 4.
Status table (as of refresh on 1bf32cc, 2026-05-13)¶
Req |
Title |
State |
|---|---|---|
R1 |
Non-orthorhombic Ewald |
MISSING |
R2 |
Multi-k MP-grid SCF |
partial, native GDF + smearing + FMIXING landed; production-size CRYSTAL14 parity bench outstanding |
R3 |
Open-shell UKS for AFM TM oxides |
partial, kernels exist, BS guess still missing |
R4 |
PW1PW hybrid functional |
partial, |
R5 |
Periodic geometry / lattice optimisation |
MISSING, gradients exist (RKS / open-shell / multi-k), no relax driver |
R6 |
Counterpoise / BSSE periodic |
MISSING |
R7 |
PBE/PBE0/B3LYP/BLYP/HSE verification |
partial, registry exists, end-to-end untested at production size |
R8 |
WC GGA functional |
partial, libxc has it, registry alias TBD |
R9 |
TOLINTEG-equivalent screening control |
partial, |
R10 |
Atomic-reference HF for atomisation |
partial, molecular UHF works, fractional-occ wrapper missing |
R11 |
D3(BJ) for periodic |
partial, molecular path exists, periodic glue missing |
R12 |
ATOMBSSE molecular dimer |
partial, molecular MP2 works, counterpoise glue missing |
R13 |
Lattice-summed exponent/coeff-deriv 3c/2c kernel |
NOT STARTED, ask raised 2026-06-21; integral-FD-behind-provider fallback unblocks P2 meanwhile |
Hand-off note¶
This document is the deliverable from basissetdev to the
periodic-methods chat. It does not prescribe how each requirement
is implemented; that is the periodic chat’s call. When a
requirement lands, mark it ✅ here and update
PLAN.md Goal 2 status. basissetdev rebases onto
main after each landing.