Repository navigation
The release that makes a result auditable and a Mac a real solver host. Every tool
call is now journalled, so a session can be exported as a Python script that
regenerates the model and its simulations. The script checks every number a solve
reported, names the exact solver binary and version that produced it, and diffs the
input deck the solver was handed. With one setting the journal also goes to disk,
where it outlasts the session. On macOS, YADE, Elmer, openEMS and Bempp now run
through the container substrate alongside OpenFOAM. That container is a new
runtime-only solver image, about a fifth of the CI image's download, signed and
scanned, and it records which solvers it contains so doctor cannot report a missing
one as ready. There is also a new explicit impact solver and one checked against an
exact closed-form answer, CalculiX that no longer blocks the MCP channel, and fixes to
STEP export and to the openEMS gate that change what a user gets back.
Added
- Session journal and
session_transcript. Every MCP tool call is recorded in
memory with its full arguments and a trimmed result.session_transcriptreturns the
session as a Python script that regenerates the model, drawings and simulations
through the same tools in a fresh worker. Handles become variables, job polls
becomes.wait(job), and absolute paths becomeWORKDIR-relative. Inspection
calls are dropped unless a later call used them, but analysis calls (hand calcs,
FEM, every*_submit) never are. Each analysis result is checked whole: every
number becomess.check, and its verdict fields (fidelity, correlation, solver,
gate pass) becomes.expect. A replay that reaches a different solver therefore
stops at that step rather than returning a plausible figure. The script opens
with aPROVENANCErecord (AnkusDrive, FreeCAD, platform, substrate, and every
solver the session reached with its path, substrate and probed version).
s.provenance()re-resolves that record on the replaying machine and prints what
moved.run_scriptcode is carried verbatim with its SHA-256
(#407,
#408,
#409,
#410,
#433). - Durable journal and
journal_export, opt-in.ANKUSDRIVE_JOURNAL_DIR(or
journal_dirin config.toml) writes one JSONL file per session: an environment
header, then one line per call with a SHA-256 of the full result. Old files are
removed oldest-first past 50 files or 512 MB, never the live session's file.
ANKUSDRIVE_JOURNAL_REDACT=1hashes paths and names, but neverrun_scriptcode; a
redacted journal can be checked but not replayed.journal_exportand
ankusdrive journal list|exportturn a past session's file into the same record
session_transcriptgives. Off by default
(#433). - Every solve records the deck it was handed. A job snapshots its case (file
list plus per-file SHA-256) when its first solver step launches, and the result
carries it asdecknext tocase_dir. On replay,s.deck(...)reports whether the
input matched, so a drifted number is attributed to the problem or to the solver
(#437). - Impact dynamics:
impact_dynamics_submit(a CalculiX*DYNAMICpenalty-contact
solve) andbar_impact(the closed form). They are gated against St-Venant's exact
elastic bar striking a rigid wall (face stressρ·c₀·v₀, contact time2L/c₀,
rebound at the strike speed) and against the plastic-wave cap past yield. This was
the last unbuilt row ofdocs/SIMULATION_NEXT.md
(#311). fem_run_submitruns a CalculiX solve as a background job, so a long FEM run no
longer blocks the MCP channel.fem_runstays for solves that take seconds
(#308).- YADE, Elmer, openEMS and Bempp run through the container substrate
(ANKUSDRIVE_SUBSTRATE=container), probed inside the running container with no
exports needed. On a Mac this brings DEM, every Elmer family, full-wave EM and
acoustic BEM in with onedocker pull
(#419). ghcr.io/gchen19/ankusdrive-solvers, a runtime-only solver image for the
container substrate: 0.88 GB compressed on arm64 and 1.15 GB on amd64, against 4.5 /
5.3 GB for the CI image. Tags::latest/:fullfor every solver, and:openfoam
for OpenFOAM alone.tools/build_solver_image.sh --solvers "…" --from-published
builds any other set in minutes with no compile. Every image writes
/etc/ankusdrive/solvers.json, and discovery reads it first, so a solver an image
leaves out is reported as "this image does not include …", never as ready
(#422).- Signed, scanned solver images. Both images carry Sigstore build provenance and a
CycloneDX SBOM, and are scanned for secrets and fixable critical CVEs.
scripts/verify-container-image.shandankusdrive doctor --verify-imagecheck an
image against this repository's workflow.doctoralso reports a container that
runs with more privilege than the documenteddocker rungrants
(#423). scripts/install-solvers.sh elmersource-builds a pinned Elmer on Linux (including
arm64, which has no package) and on macOS
(#384).pocketandholeacceptstrict=True, which escalates their "removed everything"
and "removed nothing" warnings to errors, asboolean_opalready did
(#287).solve_capabilitiesreports the case root, with its live size and the retention
policy (#437).
Changed
- Solver case directories live under one root with a stated retention. Cases are
written to<system temp>/ankusdrive-cases(ANKUSDRIVE_CASE_ROOTmoves it). Past
64 directories or 4 GB, the oldest are removed first, but never one written in the
last hour (ANKUSDRIVE_CASE_KEEP/_MAX_GB/_GRACE_S;
ANKUSDRIVE_KEEP_SCRATCH=1keeps everything). A directory you pass in is never
touched. Directories left loose in the system temp dir by earlier versions are not
moved or cleaned up
(#437). - Under the container substrate, an override the container cannot use is now
reported instead of replaced. A staleANKUSDRIVE_ELMER_PATH,ANKUSDRIVE_YADE,
ANKUSDRIVE_OPENEMS_PYTHONorANKUSDRIVE_BEMPP_PYTHON, or a host install's path
in config.toml, now leaves that family not ready. The hint names the variable and the
image's own copy that clearing it would give. Checkankusdrive doctorafter
upgrading if you moved a Mac from a native or Multipass setup
(#443,
#422). em_fullwaveis gated on the solved field. The documentedfc_ratiogate never
read the FDTD field: openEMS computes the port'sbetaanalytically, so even a
truncated run passed. A newalpha_ratiogate fits the solved field's decay below
cutoff against the exact value, and the dipole mesh is now resolved finely enough
for its resonance to be meaningful
(#398–#403).docs/SOLVERS_MACOS.mdanddocs/MACOS.mdno longer call the container-reachable
families unavailable, and recommend the solver image over the CI image. The macOS
Gatekeeper caveat is retired: a server Claude Desktop launches from a never-run,
notarized FreeCAD passes without a dialog, anddoctordiagnoses a blocked boot
(#310,
#432).
Fixed
- STEP/IGES export of an assembly wrote an empty file and reported success.
Exporting anApp::Part(links or plain features) produced 1,640 bytes with no
faces, andrelease_packageshipped that to vendors. The resolved shape is now
exported, and an export with no geometry is an error
(#434). export_shapewith noobjectexported the first shape in the document (after a
cut, the consumed base) instead of the final one. It also crashed once an FEM mesh
existed. Both are fixed at every site that walked the document the same way
(#414).- A transcript replay now lists a prepared
case_dir/sif/case/deckunder
Prerequisites instead of pointing at a directory nobody was asked to create
(#437). - A native install's
config.tomlpath is no longer sourced inside a container that
lacks it, which used to fail withblockMesh: command not found
(#422). pocket/holeno longer rejectstricton the MCP surface withTypeError
(#287).
Security
- The solver images' build inputs are pinned: CalculiX over HTTPS with a SHA-256,
preCICE by commit, and the OpenFOAM apt repo key checked instead of piped to
bash. The documenteddocker runis least-privilege (--network none,
--cap-drop ALL,--read-only,no-new-privileges, non-root)
(#423).