The baseline has always examined the machine after every run and recorded what the run left behind. It did nothing else with it: the leftovers went to the log and the evidence, and the test still reported PASS. So a check could measure correctly, walk away with the machine in a state nobody chose, and be recorded green. That is how the purge fan came to be left off by the airflow check. The leftover was not even watched, but had it been, it would have been noted and the test would have passed anyway, and an operator would still have met the airflow hold at their first fire. A post-run leftover now fails the run. One the baseline put back fails it too: the restore is the bench cleaning up after a defect, not the defect's absence. The message names what was left. The baseline watches the head as well as the motion side now: purge air on, which is how the machine idles, and the lens motor at its hold current in half step, which the lens checks and the sheet cards take and must hand back. The airflow check proves the machine is whole rather than merely measured: afterward the purge fan must read commanded-on and must draw above the floor the check itself just wrote. The pin takes forgectrl 0.1.13 (a2d73ef), which restores the idle posture after a diagnostic, fixes the lens session's takeover flag, and gives the setup a Download logs button, since the panel's Logs tab is unreachable until the setup is complete. Expect this to find things. A test that has been handing the machine back imperfectly has been passing until now, and the first campaign under the rule is where that shows.
forgetest - the ForgeFIRM release acceptance tool
The daemon behind http://<machine>:8090/ on the dev image: runs the
acceptance catalog against the machine, keeps the append-only result log,
decides which results still apply to the image that is running, exports
the release artifact scripts/release.sh gates on, and serves the bench
diagnostics page. The contract - catalog, campaigns, fingerprints,
inheritance, the gate, the coverage rule - is
the Acceptance page of the documentation site.
Run the host tests
cd forgetest
python3 -m unittest discover -s tests -v
Run the daemon on a workstation (against a mock or a manifest file)
FORGETEST_DATA=/tmp/ft FORGETEST_MANIFEST=../tree-manifest.json \
FORGECTRL_URL=http://<machine> python3 -m forgetest --port 8090
scripts/manifest-from-tree.py produces tree-manifest.json from the recipe
pins; the coverage lint is python3 -m forgetest.coverage --manifest ....
Environment
| Variable | Default | Purpose |
|---|---|---|
FORGETEST_DATA |
/data/forgetest |
results.jsonl, bench.jsonl, token, export/ |
FORGETEST_MANIFEST |
/etc/forgefirm-manifest.json |
the image manifest |
FORGETEST_PORT, FORGETEST_HOST |
8090, 0.0.0.0 | listener |
FORGETEST_BENCH_DIR |
/usr/share/forgetest/bench |
the installed bench scripts |
FORGETEST_BENCH_DATA |
<FORGETEST_DATA>/bench |
passed to bench tools: where they keep their data files (with GF_HOST=127.0.0.1 and the panel token in GF_TOKEN) |
FORGETEST_MARKER |
/run/forgetest.active |
takeover marker |
FORGECTRL_URL, FORGECTRL_TOKEN_FILE |
http://127.0.0.1, /data/forgefirm/panel.token |
forgectrl client (HTTP; the token authorizes writes from the board) |
FORGECTRL_TLS_URL |
https://127.0.0.1 |
forgectrl over HTTPS (self-signed, unverified), for the login test |
GF_SYSFS_ROOT |
/sys/glowforge/ |
kernel module sysfs |
GRBL_HOST, GRBL_PORT |
127.0.0.1, 23 | Grbl TCP |
Adding a test
Register it in the subsystem module under forgetest/suite/ with
@test(...): id subsystem.name, kind, hardware, mode (the controller
mode the test needs; the runner switches to it first), covers,
requires, always, steps. The body gets a Context (log, check, fail,
prompt, confirm, instruct, sleep, evidence, forgectrl, sysfs,
grbl, takeover). Return normally for PASS, raise runner.Failed for
FAIL. Then run the unit tests and the coverage lint.