Record audit Phase 4; LIGHTBURN: the armed window is job-based

BRINGUP gains the Phase 4 (stale-gate cluster) record - code-complete,
host-verified, hot-deployable, bench drills listed. LIGHTBURN.md now
describes the job-based armed window: relock at program end, on a
sender change, or after the spindle-off grace (counting even in Hold).
This commit is contained in:
ScottW514
2026-08-14 16:58:35 -04:00
parent daa76ca828
commit ea3fce2efd
2 changed files with 42 additions and 4 deletions
+36 -1
View File
@@ -1,11 +1,46 @@
# ForgeFIRM bring-up status & cold-start runbook # ForgeFIRM bring-up status & cold-start runbook
Last updated: **2026-08-14** — **audit remediation Phases 0 through 3 Last updated: **2026-08-14** — **audit remediation Phases 0 through 4
landed** (from an independent whole-tree audit dated 2026-08-13; the landed** (from an independent whole-tree audit dated 2026-08-13; the
remediation is sequenced behind two gates — GATE A, uncommanded energy, remediation is sequenced behind two gates — GATE A, uncommanded energy,
before any further live-fire; GATE B, control surface + release, before before any further live-fire; GATE B, control surface + release, before
any published release). any published release).
**Phase 4 (stale-gate cluster) is code-complete and host-verified; all
of it is hot-deployable (no kernel rows).** The operator-armed window
is now **job-based**, not 60-second-idle-based: it closes at program
end (`M2`/`M30`/`%`, through the kernel-idle-guarded relock so a queue
tail is never severed), whenever the sender connection changes (the
serial layer exposes a client-session generation; the press that armed
the window belongs to the displaced session), and after the disarm
grace — which now counts down in Hold, Door, and Tool Change too, so a
job abandoned in Hold no longer sits armed for hours (X-3, G-10). The
coolant fire gate is re-checked after the button wait, immediately
before the window opens (G-4), and the wait budget is clamped to
1–3600 s — garbage or zero can no longer mean wait-forever with the
latch unlocked (G-18). Cloud mode's `_button_wait` gets the same
treatment: bounded by the shared `laser_button_timeout_s`, lid
re-checked every pass, and timeout/lid/cancel all relock the latch and
disarm (C-7). The cloud cancel-drop is fixed: a settings action
rejected mid-print no longer wipes the running action's id, so a
subsequent cancel actually stops the cut (C-1). forgectrl: a
controller stop that times out restores supervision instead of leaving
the machine permanently controller-less (F-7); settings mutations are
lock-serialized and a multi-key POST lands as one atomic replace
(F-10); graceful shutdown is busy-aware — fans hold their duty and the
verdict ages out instead of being unlinked, so `forgectrl restart` no
longer feed-holds a live cut and drops exhaust (F-12; the flow-check
heater still goes off unconditionally, as this engine's own heat
source). Host verification: forgectrl and the controller build clean,
the null-sink stream harness passes all emission rules byte-identical
to the recorded baseline, and both Python clients byte-compile.
**Bench items:** finish a job and confirm disarm at Idle within the
cycle (not at +60 s); abandon a job in Hold and confirm it disarms;
kill the pump during the button wait and confirm arming refuses;
cancel a cloud print with a settings action in flight and confirm
motion stops; `forgectrl restart` mid-(dry)-cut holds exhaust. These
are dry/no-fire drills except where GATE A already applies.
**Phase 3 (broker ownership / dead-man second pass) is code-complete **Phase 3 (broker ownership / dead-man second pass) is code-complete
and host-verified.** The "broker changed who owns safing" theme is and host-verified.** The "broker changed who owns safing" theme is
closed on the code side. The supervisor writes the two safing lines closed on the code side. The supervisor writes the two safing lines
+6 -3
View File
@@ -33,9 +33,12 @@ The laser fires only inside an operator-armed window:
runs. If nobody presses within `laser_button_timeout_s` (default runs. If nobody presses within `laser_button_timeout_s` (default
300 s) the job aborts with alarm 3. Stop in LightBurn (soft reset) 300 s) the job aborts with alarm 3. Stop in LightBurn (soft reset)
cancels the wait at any time. cancels the wait at any time.
- One press covers the whole job — power changes and M5/M3 toggles do - One press covers one job — power changes and M5/M3 toggles do not
not re-prompt. The window relocks after `laser_disarm_s` (default re-prompt. The window relocks when the job ends (program end
60 s) of idle with the spindle off; the next job prompts again. `M2`/`M30`), when the sender connection changes, or after
`laser_disarm_s` (default 60 s) with the spindle off — counting even
while a job sits paused in Hold or with the lid open; the next job
prompts again.
- S-value scale: `$30` defaults to 1000, so set LightBurn's S-max to - S-value scale: `$30` defaults to 1000, so set LightBurn's S-max to
1000. 100 % power = S1000. Use M4 (variable/dynamic) mode for cuts 1000. 100 % power = S1000. Use M4 (variable/dynamic) mode for cuts
and engraves. and engraves.