Skip to content

Commit e130f90

Browse files
ivanicuclaude
andcommitted
[feat.contracts.sigma.D7+] the wire vocabulary, the ops read layer, and a docs gate that re-derives truth instead of trusting a string
Diary. Three agent lines landing together, all read-only or additive. ENVELOPE + ERROR CODES (one home, two languages). backend/envelope.py loads contracts/errors.json once and asserts the app.job_error subset relation AT IMPORT TIME by parsing migration 007 — so declaring a code a job could carry without adding it to the enum is an import failure, not a six-week drift. normalize_meta() fixes the defect that made "Net charge" and "Compute time" disappear on a cache hit: the computed and cache-hit paths returned different KEY SETS, so the UI silently lost rows. v1 compatibility is mandatory and implemented (to_v1) because the live client reads payload.cube flat; v2 is opt-in. scripts/gen_error_codes.mjs generates the TS half deterministically, and the test byte-compares the committed output against a fresh run — a generated file that has drifted is worse than no generator. 25 tests pass. OPS READ LAYER. backend/admin_queries.py: queue (with `overdue` = age > budget, which is the 36-minute runaway made visible), cache_summary, stale (raw bytes, not pg_size_pretty's string), producers, methods with their refusal lists, blob_health, toolkits, snapshot. Read-only by construction. Two numbers it surfaces that were previously narrated: 1 of 19 rows carry a method_row_id, and the orphan blob count is 11 / 35,927,489 bytes — cross-checked against bin/dirac-sweep's own predicate and an independently phrased LEFT JOIN, with the test asserting equality and refusing to average on disagreement. The DSN no longer hardcodes user=ivan, which was the one thing stopping a stranger from running this repo. 14 tests pass. DOCS GATE. scripts/check_docs_facts.mjs does not hardcode the right answer: it parses each daemon's ThreadingHTTPServer((...)) call, chases variables through os.environ.get defaults to a literal, and compares every documented host:port against that. It found a FIFTH wrong host claim the brief missed, and it kept resolving correctly while line numbers shifted under it from concurrent edits — because it matches content, not lines. It also checks every fenced bash command against package.json scripts and real paths. Wired as gate 6; the suite is now six gates and all pass. One claim in the brief was REFUTED rather than fixed, which is the outcome I want from these sweeps: the "documented build command omits the rdkit asset copy" defect was already fixed upstream in 3f0662d, proven empirically by moving the assets aside and running only the documented command. Nine findings about MY OWN contract files are recorded in the agent's report and owed: iface.pyi's ErrorCode Literal lists a BAD_BASIS that exists nowhere and omits three codes that do; FieldMeta is missing ~18 keys the code really emits; iface.d.ts says envelope:1 where SPEC.md says 2. The contracts drifted from the code within a day of being written, which is exactly why the generated half exists. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F2MSV6FzZHf2hjz898RKZ7
1 parent 0c4e92d commit e130f90

11 files changed

Lines changed: 2779 additions & 7 deletions

File tree

‎README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ Dirac is **one integrated app** with multiple facets, all sharing the same mol\*
2323
The core workflow stays 100% in-browser. The **Fields** facet is the one exception by design — real SCF does not belong in wasm. It talks to a local daemon that turns the focused ligand's molfile into Gaussian-cube scalar fields (already in scene coordinates):
2424

2525
```bash
26-
backend/env/bin/python backend/field_server.py # 127.0.0.1:8901; the Fields tab shows online/offline honestly
26+
backend/env/bin/python backend/field_server.py # 0.0.0.0:8901 (LAN-reachable, unauthenticated); the Fields tab shows online/offline honestly
2727
```
2828

29-
Self-contained conda env in `backend/env` (RDKit 2026.03 + pyscf 2.14). MEP is instant; HOMO/LUMO/density/QM-MEP run a real RHF/UHF (STO-3G default, 6-31G optional) and refuse to render if SCF does not converge.
29+
Self-contained conda env in `backend/env` (RDKit 2026.03 + pyscf 2.14). MEP is instant; HOMO/LUMO/density/QM-MEP run a real RHF/UHF (STO-3G default; 6-31G, 6-31G\*, or def2-SVP on request) and refuse to render if SCF does not converge.
3030

3131
## Run it
3232

‎backend/README.md‎

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ step anywhere.
88
## Run
99

1010
```bash
11-
backend/env/bin/python backend/field_server.py # 127.0.0.1:8901
11+
backend/env/bin/python backend/field_server.py # 0.0.0.0:8901
1212
```
1313

1414
`backend/env` is a self-contained conda env (gitignored): RDKit 2026.03 +
@@ -19,6 +19,18 @@ pyscf 2.14 + numpy. Recreate with:
1919
backend/env/bin/pip install rdkit pyscf numpy
2020
```
2121

22+
## Security posture
23+
24+
Bound to **all interfaces** (`0.0.0.0`), not loopback — Ivan drives this from
25+
a Mac on the LAN, and a loopback-only daemon just reports "offline" there.
26+
Stated rather than discovered: it is **unauthenticated** and runs quantum
27+
chemistry on whatever molfile is POSTed to it. A `Host`/`Origin` allowlist
28+
(this box's own hostnames/addresses) blocks DNS-rebinding and drive-by reads
29+
from a page opened elsewhere, but anyone who can already reach this machine
30+
on the LAN can submit compute. There is no DELETE route on this daemon —
31+
`app.field_cube` / `app.blob` rows are only ever removed by a human running
32+
`bin/dirac-sweep` by hand.
33+
2234
## Protocol
2335

2436
| Route | In | Out |
@@ -27,7 +39,8 @@ backend/env/bin/pip install rdkit pyscf numpy
2739
| `POST /field` | `{molfile, kind, basis?}` | `{ok, cube, meta}` or `{ok: false, error}` |
2840

2941
Kinds: `mep` (Gasteiger/Coulomb, ~0.1 s) · `homo` · `lumo` · `density` ·
30-
`mep_qm` (pyscf HF + cubegen). `basis`: `sto-3g` (default) or `6-31g`.
42+
`mep_qm` (pyscf HF + cubegen). `basis`: `sto-3g` (default) · `6-31g` ·
43+
`6-31g*` · `def2-svp` (needed for Br/I — 6-31g\* has no iodine ECP).
3144

3245
## Persistent cube cache
3346

@@ -64,5 +77,15 @@ direct negative control: SQLSTATE 23514).
6477
| Fe-heme (75 atoms) | DIIS stalls at 120 cycles → SOSCF rescue, minutes |
6578

6679
Known limits: `MAX_QM_ATOMS = 120` (with hydrogens); transition-metal ligands
67-
are minutes, not seconds; no request cancellation — the panel's busy state is
68-
per-page and one compute runs at a time.
80+
are minutes, not seconds.
81+
82+
## Concurrency
83+
84+
`ThreadingHTTPServer` — every request runs on its own thread, so **concurrent
85+
compute is unbounded**: nothing here queues or rejects a second SCF while a
86+
first is running. There is still no request *cancellation* (a client that
87+
gives up cannot stop the thread already computing for it), but each SCF is
88+
individually **deadline-bounded**: a watchdog fires inside the SCF loop
89+
(`max_seconds`, default 90 s, clamp 900 s) and unwinds with an error instead
90+
of running to `max_cycle` — so a stuck computation cannot hold a thread
91+
forever, only up to its own budget.

0 commit comments

Comments
 (0)