From 0cb9044e1d6438e096a0be890c30c8a34872cb27 Mon Sep 17 00:00:00 2001 From: ScottW514 Date: Sat, 22 Aug 2026 19:59:36 -0400 Subject: [PATCH] forgetest: the offline jobs removed after each test; the record of the first offline campaign Every offline test now removes the jobs it wrote under /tmp/forgetest on its way out (the bench rule: nothing left behind in the session that put it there). CAMPAIGN-LOG gets the 2026-08-22 entry for dev image 20260822232347: the offline service dry-checked, then campaign c-20260822233344-08de, 13 run and 43 of 43 with the four offline tests in 5.5 minutes, and what the machine said under it. BRINGUP: the offline service is done and bench-validated. --- docs/BRINGUP.md | 10 ++++---- docs/CAMPAIGN-LOG.md | 39 ++++++++++++++++++++++++++++++ forgetest/forgetest/suite/cloud.py | 13 ++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/docs/BRINGUP.md b/docs/BRINGUP.md index df20889..2e0ee7c 100644 --- a/docs/BRINGUP.md +++ b/docs/BRINGUP.md @@ -1155,11 +1155,11 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`. (the operator channel, the merged mode-switch, the sensor witnesses, the steps pane, the journal, per-test implementation hashing) is done and bench-validated (CAMPAIGN-LOG 2026-08-22). The offline cloud - service for the machine-behavior tests is code-complete (gfutilities - `OfflineService`, `gfcloud --offline`, `forgetest/puls.py`, four tests - re-ported) with host replays; **its bench run on the next dev image is - owed.** A bench actuator for the lid, interlock and button is planned, - not started. Catalog + service for the machine-behavior tests (gfutilities `OfflineService`, + `gfcloud --offline`, `forgetest/puls.py`, four tests re-ported) is done + and bench-validated on dev image `20260822232347` (43 of 43, the four + offline tests in 5.5 minutes, nothing on the bed). A bench actuator for + the lid, interlock and button is planned, not started. Catalog gaps left from the tool's own plan: `cooling.confirm-escalate` and `cooling.fire-gate-blocks-arm` are not ported (both need the pump switched by hand mid-run, so they are bench-tab material first), and whether diff --git a/docs/CAMPAIGN-LOG.md b/docs/CAMPAIGN-LOG.md index ac2e2d1..1c90784 100644 --- a/docs/CAMPAIGN-LOG.md +++ b/docs/CAMPAIGN-LOG.md @@ -3503,6 +3503,45 @@ campaign asked for was performed by the operator and recorded so in the evidence; a bench actuator, when there is one, takes the same calls. +## 2026-08-22: the machine's print behavior without the service + +Dev image `20260822232347` (forgefirm 628f2f7; python3-gfutilities 768730e +and python3-gfhardware a3ca36f pinned by meta-openglow a52e68c and the +forgefirm-app pin), the first image with the offline service: gfcloud +restarted under the `/run/gfcloud-offline` marker comes up with no +account and no network, takes the service's action messages on +`/run/gfcloud-offline.sock`, and hands the machine's events back. Four +cloud tests run on it with a job synthesized on the board +(`forgetest/puls.py`: a factory print's header over a square the laser is +never commanded on): the lid and interlock aborts, the button-wait +cancel, a paused print ended by the lid, and a print longer than the ring +ended the way the app ends one. Nothing on the bed; the arm press is the +operator's only hand on a print. + +Before the operator's run the plumbing was dry-checked from a shell: +stop, marker, start, the `OFFLINE service` line and the socket, a +`settings` action answered `settings:completed`, then a restart without +the marker and the web session `ready` again. One lesson from the dry +script, not the harness: the marker has to stay until the offline line +is logged, because the supervisor reports the client running seconds +before Python has finished importing and read it. + +Campaign `c-20260822233344-08de`: 30 of 43 inherited across the pin bump +(the catalog's covers put every `cloud.*` test on the moved components, +and the core always runs), **13 run, 13 PASS, 43 of 43, release +authorized**; 11 minutes of test time, the four offline tests 5.5 of it. +No release cut. What the machine said under the offline service: the +lid edge to the stop 10 ms; the button-wait cancel with no run started; +the paused print cancelled by the lid, parked to the job start, latch +locked, button dark; the long job (33.4 MiB of ticks in an 87 kB gzip) +live-fed with the kernel's program total climbing 33.29 to 34.60 MB while +the report divided by the job's 35.0 MB, no underrun, the backtrack held +at 164 214 steps, the pause and resume taken, and the cancel's tail the +same as the lid's. Every print's `print:running`, +`print:return_to_home:succeeded` and `print:cancelled` came back over +the socket. The real service was still proven on the same image by +`cloud.mode-switch` and the one real print, `cloud.pause-resume`. + ## Superseded status notes ### Shared machine services — remaining polish, as listed 2026-08-13 diff --git a/forgetest/forgetest/suite/cloud.py b/forgetest/forgetest/suite/cloud.py index 65c8140..f43145d 100644 --- a/forgetest/forgetest/suite/cloud.py +++ b/forgetest/forgetest/suite/cloud.py @@ -720,6 +720,15 @@ def offline_events(off): return [e.get("event") for e in off.events if e.get("event")] +def offline_cleanup(ctx): + """The jobs the offline tests wrote are gone when the test is (tmpfs + would lose them at reboot; the bench rule is sooner).""" + import shutil + if os.path.isdir(JOB_DIR): + shutil.rmtree(JOB_DIR, ignore_errors=True) + ctx.log("offline jobs removed from %s", JOB_DIR) + + def offline_job(ctx, name, **kw): """Write a synthesized, laser-never-commanded job for the offline service and return its path (under JOB_DIR, tmpfs).""" @@ -858,6 +867,7 @@ def lid_interlock_abort(ctx): lid_interlock_abort_body(ctx, ev, off, job, offset) finally: off.__exit__(None, None, None) + offline_cleanup(ctx) def lid_interlock_abort_body(ctx, ev, off, job, offset): @@ -956,6 +966,7 @@ def lid_during_button_wait(ctx): lid_during_button_wait_body(ctx, ev, off, job, offset) finally: off.__exit__(None, None, None) + offline_cleanup(ctx) def lid_during_button_wait_body(ctx, ev, off, job, offset): @@ -1135,6 +1146,7 @@ def oversize_stream(ctx): oversize_stream_body(ctx, ev, off, job, offset, before) finally: off.__exit__(None, None, None) + offline_cleanup(ctx) def oversize_stream_body(ctx, ev, off, job, offset, before): @@ -1252,6 +1264,7 @@ def paused_lid_cancel(ctx): paused_lid_cancel_body(ctx, ev, off, job, offset) finally: off.__exit__(None, None, None) + offline_cleanup(ctx) def paused_lid_cancel_body(ctx, ev, off, job, offset):