Commit Graph
330 Commits
Author SHA1 Message Date
ScottW514 8654c36e99 BRINGUP: forgetest bench campaign 2026-08-16 - 22/26, motion and cloud green, the live tests remain 2026-08-16 14:22:32 -04:00
ScottW514 5002d59dd7 ACCEPTANCE: the fresh-boot reference is taken after a power cycle; the head-return rule 2026-08-16 14:22:08 -04:00
ScottW514 a80d7aabfb forgetest: cloud tests prove the session from the client's log and hand the head back
cloud.mode-switch took the optional connect-time firmware probe file as
the evidence of a live session and failed on a bench where that check is
off; the evidence is now gfcloud's own authenticate/ws-connect lines in
the unified log after the switch, the probe recorded when present. Cloud
mode's connect clears the kernel position counters at the head's start
and its hunt homes the head to the corner: the test tells the runner the
counters were re-zeroed (Context.counters_rezeroed) and jogs the head
back by the counter-measured displacement, and hands the lid lamp back
at the level it found. cloud.gfhome-homing documents that it leaves the
machine homed at the corner.

Baseline: a displaced head is jogged back along its own path by the
kernel-measured X/Y delta through the GRBL controller (bounded 100 mm,
waits out a controller respawn backoff); Z is never touched.
2026-08-16 14:21:54 -04:00
ScottW514 d4e2f85538 forgetest: motion tests end on the machine's idle; the Grbl client survives a soft reset
wait_idle returned on a stale Idle before a just-commanded move began,
and the tests declared PASS on grblHAL's Idle while the kernel still
played the stream depth and the decel tail (the baseline caught
state=running after motion.pacing). Every motion test now ends on
forgectrl's idle (machine_idle), and wait_idle ignores an Idle inside a
short grace unless a non-Idle state was seen.

status_report re-sends '?' every 0.5 s until a report arrives: a soft
reset (^X) flushes the controller's read buffer and eats a '?' that lands
in it - the bench saw motion.cancel-abort error with no report for 5 s
after the abort while the controller answered the next '?' at once.

motion.deadman: the SIGSTOP drill waited for a running controller and
got the killed pid back before the supervisor reaped it (drill 1 already
waited for a different pid); and the forgectrl-restart drill expected the
busy controller's pid to survive the retake, but a retake under the
broker is stop-at-idle, re-probe, start a supervised controller (the old
inherited fd cannot be adopted) - the check is now: the move finished
unmanaged, supervision came back running and verified. Bench-proven
2026-08-16: kill respawn 1.3 s, hang -> underrun 0.21 s, retake at idle.
2026-08-16 14:21:53 -04:00
ScottW514 0312dec22b BRINGUP: forgetest bench campaign 2026-08-16 - 14/26, the baseline rule, the masked-probe finding 2026-08-16 13:36:59 -04:00
ScottW514 13beb51e26 forgetest: kernel.k1-k2 leaves the position counters where it found them
K2 streamed 1000 masked +X steps; the counters advanced although nothing
moved, and forgectrl's position display carried the offset. The stream
now runs 1000 out and 1000 back, and the counters returning to start is
a check. Bench-proven 2026-08-16: (0,0,0) before and after.
2026-08-16 13:35:20 -04:00
ScottW514 4aaedc8080 forgetest: every run starts from, and leaves, the fresh-boot idle state
A baseline pass brackets every test and bench tool: before the run the
machine is verified against the fresh-boot idle state and anything off it
is restored; after the run - pass, fail, or abort - it is restored again.
Fixed items are the resting values the boot establishes (module defaults,
forgectrl's start-up writes, the GRBL controller's init writes) and
forgectrl's idle picture (controller running with motion verified, no
diagnostic, camera and cooling engines idle); preserved items (lid lamp
level, position counters, settings map, controller mode) are captured
before and handed back after. Deviations are leftovers: in the run pane,
in the result's evidence, and on the page - attributed to the previous run
when found before, to the run itself when found after.

forgetest takes a fresh-boot reference once per boot (within ten minutes
of boot, after the supervisor settles) as the session's resting lid-lamp
level and the check on the fixed values; the values were confirmed
against a fresh boot of the dev image on the bench (step_freq rests at
28160, the controller's default tick, not the probe's 10000).

Takeover runs capture the controller-owned kernel attributes on entry and
write them back before forgectrl restarts: the bench found the kernel
tests leaving motor_lock=15 behind, which masked the supervisor's
liveness probe - no motion by construction, a false driver-wedge verdict,
the rail-off ladder, and finally motion-fault. The takeover wrapper also
waits for the supervisor to settle on both sides (moved into baseline).

Catalog consequence: none beyond the runner; the tests' own drills are
unchanged.
2026-08-16 13:35:19 -04:00
ScottW514 799e0e829c forgetest: a takeover waits for forgectrl to settle on both sides
forgectrl's supervisor probes motion liveness on every start - a small
head move verified by the accelerometer, with a rail-off ladder of up to
about 70 s on a dead verdict. The takeover wrapper returned as soon as
forgectrl start succeeded, so a test that followed found the machine
busy (bench: cooling.flow-verify refused with 409 machine is not idle
13 s after kernel.fire-abu), and back-to-back takeover tests stopped
forgectrl mid-probe. The wrapper now waits for /mode to settle - motion
verified, motion-fault (logged as a warning), or standby - before it
stops forgectrl and again after it starts it, giving up after 10 s when
forgectrl does not answer at all (the host, or a daemon that is down).
No catalog consequence: the takeover tests' own drills are unchanged.
2026-08-16 13:09:56 -04:00
ScottW514 a4b757add5 forgetest: a diag start is 202 Accepted with started:true
forgectrl answers a started diagnostic with 202 (an async job); the
cooling.flow-verify test asserted 200 and failed on the bench before the
diagnostic ran. No catalog consequence beyond the test's own source
hash.
2026-08-16 13:08:48 -04:00
ScottW514 e19e7c5304 BRINGUP: images 20260815215236 / 20260815215332 built with the logging catalog and the fast sanitizer 2026-08-15 17:54:47 -04:00
ScottW514 d7d68c556e BRINGUP: the swept legacy logs were deleted from the bench 2026-08-15 17:51:22 -04:00
ScottW514 d17655c3c0 forgetest: logs.routing and logs.level-settings; export gets its own timeout
The routing test proves the path every logger takes and stands for the
emitters and relays in every component (fflog in forgectrl and grblHAL,
the SysLogHandler in the Python apps, the supervisor's per-controller
relay, the daemon's fifo relay, the render step): one logger daemon,
rendered rules and the effective record consistent with /logs, the tree,
the daemon's own emitter line, `logger` probes routed by program name in
the ff_line format, a stray program only in system/, kernel lines, relay
processes, nothing written outside the tree. The level-settings test
covers the validators and the configured-vs-effective / pending_reboot
contract. Both PASS on the bench with the existing logs.tree-tail-export
through the real Runner. That test's export call now uses a 300 s client:
the sanitized export took 13.9 s on the target and tripped the 10 s
default. Pin: forgectrl 4d19e9d (the sanitizer skips passes a line
cannot match; 4x faster). Coverage lint enforced: 0 uncovered.
2026-08-15 17:44:44 -04:00
ScottW514 07141d60fc BRINGUP: remote syslog verified over the real hop (UDP + TCP, collector outage + queued delivery) 2026-08-15 17:24:45 -04:00
ScottW514 2e82b13438 BRINGUP: $H gfhome routing verified; item 14 closed 2026-08-15 16:31:31 -04:00
ScottW514 7baa6a0352 BRINGUP: unified logging bench validation complete (levels, remote, rotation, export, RT, respawn, cloud routing) 2026-08-15 16:26:58 -04:00
ScottW514 16deb4896f forgetest: /fuse-identity is two-factor; the auth test asserts both refusals
forgectrl reveals the fuse identity only to the token AND the physical
button held, so the token alone must answer 403 with the button message.
The test now asserts the no-token refusal and the token-without-button
refusal and never fetches the identity itself (a 200 would have carried
the fuse password into the result log). BRINGUP: the bench campaign on
the flashed dev image, 7 of 24 passed so far.
2026-08-15 16:07:12 -04:00
ScottW514 5e04f4f4cd BRINGUP: forgetest CI is green on the pushed tree 2026-08-15 15:58:56 -04:00
ScottW514 1179d5e7c1 Release acceptance gate: release.sh refuses to sign without a matching artifact
scripts/acceptance-gate.py recomputes every catalog test's domain fingerprint
from /etc/forgefirm-manifest.json inside the release rootfs and requires the
committed releases/v<version>/acceptance.json to carry a matching PASS
(inherited results not core and newer than the invalidate epoch; the artifact
self-hashed; the catalog identical to the tree). release.sh runs it after the
build and stages the artifact as a release asset; FORGEFIRM_ACCEPTANCE_SKIP=1
bypasses loudly. scripts/manifest-from-tree.py builds the same manifest from
the recipe pins with git for CI and the workstation; forgetest-ci.yml runs the
unit tests and enforces the coverage lint (every manifest path covered by some
test). docs/ACCEPTANCE.md is the contract; the coverage currency rule and the
status live in BRINGUP.
2026-08-15 15:57:12 -04:00
ScottW514 c0f53a865f forgetest: the release acceptance tool and the bench diagnostics page
A stdlib-only daemon on the dev image (HTTP :8090) that runs the acceptance
catalog against the machine from a self-contained page, keeps the append-only
result log under /data/forgetest, and exports the release artifact the gate
reads. Tests declare kind (auto / operator / live), hardware (api / takeover),
coverage globs, prerequisites, and core membership; a test's domain
fingerprint is the hash of the manifest files its globs select plus the
platform and its own implementation, so a PASS stays valid exactly while
nothing it covers changed. Campaign rules: a FAIL ends the campaign, the core
(image health, kernel latch and drills, one live emission witness) is never
inherited, invalidate-all forces a full campaign, no SKIP. Live tests need the
operator acknowledgment and the physical arm press through the controller;
takeover tests stop forgectrl for the duration with a crash-recoverable
marker; the tool never touches the laser latch.

Catalog v1: 24 tests ported from the proven bench drills with their recorded
pass criteria (image, kernel K1-K3 and fire A/B/U, forgectrl API and logs,
motion incl. dead-man, cooling, live laser, camera, update, cloud). The bench
tab lists every scripts/bench tool and runs the board-side ones as
subprocesses (takeover tools wrapped). 44 host unit tests, including the gate
verification fixtures. Installed only by forgefirm-image-dev, with the bench
scripts under /usr/share/forgetest/bench.
2026-08-15 15:57:11 -04:00
ScottW514 9b5558dfbc meta-forgefirm: the image manifest (/etc/forgefirm-manifest.json)
Every image records the identity of its build inputs. forgefirm-manifest.bbclass
gives a component recipe a per-file source fingerprint (git ls-tree blob ids,
submodules recursed; file:// sources hashed with git hash-object); the kernel
and glowforge.ko publish theirs through do_deploy because kernel-module-split
leaves the module recipe's main package empty. forgefirm-image-manifest.bbclass
assembles the entries with the platform identity - machine, modules directory,
device tree hashes, layer content hashes (meta-forgefirm and the meta-openglow
layers by content, the kas-managed layers by revision) - into
/etc/forgefirm-manifest.json and deploys a copy next to the image. Layer
revisions and dirty flags stay outside the identity, so a rebuild from an
unchanged tree keeps its content hash and the release and dev images of one
build share it. The acceptance tool and the release gate read this file.
2026-08-15 15:57:10 -04:00
ScottW514 da3725c6de BRINGUP: drop the acceptance-tool text that was swept in from the shared working tree
It belongs to work in progress in another session; committing it here was a mistake. The working tree still carries it uncommitted.
2026-08-15 15:28:39 -04:00
ScottW514 304c4e7186 BRINGUP: unified logging bench checks on the flashed dev image 2026-08-15 15:27:48 -04:00
ScottW514 7487f907f4 logging: default rules come from the init script, not a trailing fallback rule
rsyslog flagged the fallback action after the include as unreachable (the rendered rules end in stop). The forgefirm-logging init script now writes a default rules file when the render leaves none, and the shipped rsyslog.conf carries only the include.
2026-08-15 15:27:24 -04:00
ScottW514 298d711533 rsyslog: stop last at shutdown (K95), after the controllers and forgectrl 2026-08-15 15:07:15 -04:00
ScottW514 e733bbc270 forgefirm-app: bump PV with the SRCREV move 2026-08-15 14:37:57 -04:00
ScottW514 6050c0e703 Unified logging: rsyslog as the system logger, the ForgeFIRM log tree
rsyslog replaces busybox syslogd/klogd (VIRTUAL-RUNTIME_base-utils-syslog,
trimmed PACKAGECONFIG) and becomes the only log writer: the appended
/etc/rsyslog.conf sets the inputs and the ff_line format and includes
the per-logger rules that `forgectrl --render-syslog` renders from the
machine settings at boot. forgefirm-logrotate becomes forgefirm-logging:
render before rsyslog starts (S19), sweep the pre-syslog log files into
/data/forgefirm/legacy-logs once, and rotate the tree at boot and hourly
by rename + HUP instead of copytruncate. Pins bumped to the pushed
forgectrl (syslog emitter, Logs tab, export), grblHAL-glowforge (syslog
emitter) and python3-gfhardware apps (syslog handlers, capture dir);
the CI harnesses set FFLOG_STDERR=1 so failure diagnostics keep the
controller's log lines. BRINGUP carries the bench validation checklist
(Next work item 14); this is an image change and rides the next flash.
2026-08-15 14:37:33 -04:00
ScottW514 b08e5ab929 BRINGUP: clarify the pre-rename estop references in dated records 2026-08-15 14:16:34 -04:00
ScottW514 3f81597c93 SAFETY: hv_enable run-boundary behavior is established; drop it from the open items 2026-08-15 14:11:32 -04:00
ScottW514 7319c718fe SAFETY/BRINGUP: HV watchdog one-shot measured pulse-to-drop, t_w = 454 +/- 3 ms 2026-08-15 14:01:46 -04:00
ScottW514 52b398e11d cp_watchdog_timing: do not starve the controller (no nice, sleep per pass), two jogs 4 s apart 2026-08-15 13:54:48 -04:00
ScottW514 fe6a65b7fe bench: cp_watchdog_timing.py - measure the HV watchdog one-shot from the SoC pins 2026-08-15 13:49:50 -04:00
ScottW514 d7cb506c46 BRINGUP: hv_enable readback bench-validated on image 20260815162923 2026-08-15 13:36:51 -04:00
ScottW514 87a8ccbd59 BRINGUP: image 20260815162923 built on the hv_enable pins; flash pending 2026-08-15 12:41:52 -04:00
ScottW514 f75629a4df hv_enable: EV_SW bit 4 is the HV_ENABLE readback; pins for the rename
SAFETY.md and the safing figure name GPIO4_06 for what it is - the
readback of the chain's HV_ENABLE output through U24 (the factory net
label E-STOP is kept as a note); BRINGUP records the rename, the
device-tree polarity flip that makes bit 4 read as HV_ENABLE itself,
the removal of the estop_halts_motion opt-in, and the bench check for
the flash that ships it. Recipe pins move to forgectrl 801f1f3,
grblHAL-glowforge b629c18 and python3-gfhardware c3d1790 (PV 0.1.5).
2026-08-15 12:28:58 -04:00
ScottW514 8a1fa91db5 bench: net-blip tool; BRINGUP - cloud-mode drills, lid-IR tracks the lid LED, fire gate back to watch-only 2026-08-15 12:06:16 -04:00
ScottW514 1d4c6b5a57 BRINGUP: LightBurn connects after an idle lid cycle on 20260815154622; further LightBurn door-open issues tracked as Next work item 12 2026-08-15 11:57:40 -04:00
ScottW514 8658973d5c Bump pins: grblHAL a9446fe (door signal hidden while idle/jog/homing), forgectrl f7276c5; docs
LIGHTBURN: lid open mid-job = Door, Resume continues; the lid is free at idle. SAFETY/SERVICES/BRINGUP: the visibility policy and its bench check.
2026-08-15 11:44:39 -04:00
ScottW514 81fca45cb5 BRINGUP/SAFETY: interlock latch drive and watchdog readback bench-validated on image 20260815150546
Loop pull sets interlock_latch_reset + interlock_latch within one 50 ms sample and both clear on reinsert; charge_pump_alive tracks the run and falls 0.45 s after the last charge-pump pulse (matches the measured R*C); estop follows it on both edges. Note that an interlock trip parks grblHAL in Door:0 until a cycle start.
2026-08-15 11:27:25 -04:00
ScottW514 21d3a482c6 Laser safety write-up (docs/SAFETY.md + diagram); bump pin: forgectrl a451e7c
docs/SAFETY.md documents the control board's laser safing chain as
reverse-engineered and bench-verified - parts, every net with its SoC pin,
Linux exposure and polarity, the logic, and the software layers ForgeFIRM
stacks on it - with docs/img/safety-chain.svg. Linked from the README.

BRINGUP: Next work item 11 records the interlock-latch finding (an open
loop never tripped the latch; the kernel now drives INTERLOCK_LATCH_RESET)
and the charge-pump watchdog readback, both code-complete and pinned,
bench validation on the next image.
2026-08-15 11:03:15 -04:00
ScottW514 43cc540a09 Bump pins: forgectrl 73eda9a, grblHAL 91807a2 (head-presence gate, honest labels); BRINGUP head-absent record 2026-08-15 09:19:25 -04:00
ScottW514 f919f2e622 BRINGUP: lid-IR flame signature measured - a candle reads +3..6 counts, same as a cut 2026-08-15 09:07:55 -04:00
ScottW514 984c0697e3 BRINGUP: LED sequence operator-witnessed 2026-08-15 09:02:38 -04:00
ScottW514 744376d8e8 BRINGUP: the lid-IR fire gate is set on the bench 2026-08-15 08:58:01 -04:00
ScottW514 e1207316ec bench: fd-scan tool; BRINGUP session record - dry drills, homing witness, panic drill 2026-08-15 08:52:51 -04:00
ScottW514 31ac4bbcbd Bump pins: forgectrl 3edb7bd, grblHAL 5960f05 (stop-lever fix, fetch-verified) 2026-08-15 08:43:50 -04:00
ScottW514 5848eea6f7 BRINGUP: bench session record - lid-IR gate sized, expected-stop lever defect found, fixed, re-proven 2026-08-15 08:42:32 -04:00
ScottW514 cced57da6c bench: platform drills, cutting-power lid-IR and expected-stop live drills, SIGTERM lifecycle case
- platform_drills.py (on the board, forgectrl stopped): dead-man trip
  readback, rmmod/modprobe with concurrent attr reads, decay/microstep
  readback, LED sequence.
- live_fire_drills.py: ircut (S/F selectable characterization job),
  expstop (armed job + POST /controller/stop, controller left stopped),
  ctrlstart (separate, operator-approved resume); the token header is sent
  in exact case.
- laser_lifecycle_test.py: sigterm-mid-job - SIGTERM during an armed job
  must stop it, relock the latch and exit promptly.
2026-08-15 08:38:29 -04:00
ScottW514 8ef2d2845a BRINGUP: consolidate the outstanding bench validations into Next work 2026-08-15 07:26:22 -04:00
ScottW514 21488f74fd BRINGUP: image 20260815105250 flashed; carry the two deferred daemon items in Next work
The forgefirm-app recipe states why its packages are MIT-only.
2026-08-15 07:21:17 -04:00
ScottW514 76bf87939f BRINGUP: image 20260815105250 built on the hygiene-sweep pins 2026-08-15 07:08:39 -04:00