feat(irv-ml1): provision the Draupnir geometry engine, acceptance-tested

Operator-authorized. build123d 0.12.0 + OCP, numpy 2.4.6, trimesh 5.1.0 in a
3.11 venv, FreeCAD 1.0.0 headless as an AppImage, artifact root on smithy.

The acceptance test is the point and it PASSES: brokkr-smithy-dev shipped a
contrastive control pair whose every property is construction-known, so the
install is checked against arithmetic rather than against a render. Both parts
build, both bounding boxes are exactly 40x40x5, and both volumes match to float
tolerance. These scripts had never been executed by anyone -- build123d is
deliberately absent from the authoring box -- so this was their first run.

FreeCAD is an AppImage BY CHOICE: the distro package drags a GUI/Qt dependency
tree onto a host running twelve GPU and audio services, where an AppImage is
self-contained, pinned and removable with one rm.

Slicer DEFERRED rather than guessed. PrusaSlicer's latest release ships no
Linux AppImage at all, and a guessed release filename had already produced a
4 KB error page in this same session. It is the one item they said could lag.

Two things worth keeping in the header: irv-ml1's ssh config pins the gitea
host to gitea_brokkr_smithy with IdentitiesOnly, whose comment is
irv-ml1-r14-deploy and NOT the arbo key that sorts first in ~/.ssh/*.pub -- I
registered the wrong one first, and the failure names the right one. And
`ssh irv-ml1` is lkraven with no NOPASSWD sudo while `ssh infra-ops@irv-ml1`
has it, so only the artifact-root step needs the other identity.

The deploy key was registered with claude-bot's own token rather than the
operator's site-admin token -- the org grant from earlier today doing real work
on its first use.
This commit is contained in:
vh
2026-09-21 11:17:41 -07:00
parent 07c9cb293b
commit 34c4179d55
+77
View File
@@ -0,0 +1,77 @@
# Provision the Draupnir geometry engine on irv-ml1.
#
# scripts/elway irv-ml1 --playbook playbooks/irv-ml1-draupnir-engine.yaml
#
# Records what was VERIFIED on 2026-09-21, not what was planned.
#
# ⚠ SUDO IDENTITY. `ssh irv-ml1` is lkraven and has NO NOPASSWD sudo;
# `ssh infra-ops@irv-ml1` does. The only step needing root is the artifact
# root, so everything else runs as lkraven, where the ssh config and deploy
# keys live.
#
# ⚠ DEPLOY KEY. irv-ml1's ~/.ssh/config pins gitea.phasefinal.com to
# `gitea_brokkr_smithy` with IdentitiesOnly yes — its comment is
# "irv-ml1-r14-deploy", NOT the arbo key that sorts first in ~/.ssh/*.pub.
# Registering the wrong one fails with a message naming the right one, which is
# the clue. The key is registered read-only on pfi/draupnir (id 8).
#
# ⚠ FreeCAD is an AppImage BY CHOICE. The distro package drags a GUI/Qt
# dependency tree onto a box running twelve GPU and audio services; an AppImage
# is self-contained, pinned, and removable with one rm. Run it as
# `FreeCAD.AppImage --appimage-extract-and-run freecadcmd`.
#
# ⚠ SLICER DEFERRED. PrusaSlicer's latest release ships NO Linux AppImage
# (Windows/macOS only), and guessing at a release filename already produced a
# 4 KB error page here once. Left undone deliberately rather than done blind.
vars:
repo: git@gitea.phasefinal.com:pfi/draupnir.git
checkout: /home/lkraven/development/draupnir
freecad_url: https://github.com/FreeCAD/FreeCAD/releases/download/1.0.0/FreeCAD_1.0.0-conda-Linux-x86_64-py311.AppImage
steps:
- name: Artifact root on smithy (500 GB budget, per draupnir remote.py)
sudo: true
shell: mkdir -p /mnt/smithy/draupnir && chmod 2775 /mnt/smithy/draupnir
creates: /mnt/smithy/draupnir
- name: Clone the engine repo
shell: git clone {{ repo }} {{ checkout }}
creates: "{{ checkout }}/.git"
- name: uv venv on the 3.11 floor
shell: cd {{ checkout }} && uv venv --python 3.11
creates: "{{ checkout }}/.venv/bin/python"
- name: Install the engine extra (build123d + OCP + numpy + trimesh)
shell: cd {{ checkout }} && uv pip install -e '.[engine]'
# Idempotent on the INSTALLED package, not on the venv existing.
when: "! {{ checkout }}/.venv/bin/python -c 'import build123d' 2>/dev/null"
- name: FreeCAD headless AppImage
shell: mkdir -p ~/opt && curl -sL -o ~/opt/FreeCAD.AppImage {{ freecad_url }} && chmod +x ~/opt/FreeCAD.AppImage
creates: /home/lkraven/opt/FreeCAD.AppImage
verify:
- name: build123d, numpy and trimesh all import
shell: "{{ checkout }}/.venv/bin/python -c 'import build123d, numpy, trimesh, OCP'"
changed_when: "false"
- name: FreeCAD runs headless
shell: ~/opt/FreeCAD.AppImage --appimage-extract-and-run freecadcmd --version
changed_when: "false"
- name: artifact root is writable by the docker group
shell: test -w /mnt/smithy/draupnir
changed_when: "false"
# The real gate. Both control parts must BUILD and both volumes must match
# construction-known arithmetic — not a render, not an opinion.
- name: acceptance — contrastive control pair builds with correct volumes
shell: >-
cd {{ checkout }} && .venv/bin/python -c
"import math,runpy;
g=runpy.run_path('parts/plate-good/model.py')['result'];
t=runpy.run_path('parts/plate-thin-wall/model.py')['result'];
wg=40*40*5-math.pi*5**2*5; wt=40*40*5-math.pi*19**2*5;
assert abs(g.volume-wg)<1e-6*wg, (g.volume,wg);
assert abs(t.volume-wt)<1e-6*wt, (t.volume,wt);
assert (round(g.bounding_box().size.X,6),round(g.bounding_box().size.Z,6))==(40.0,5.0);
print('acceptance OK')"
changed_when: "false"