Record the download guards and the feed watchdog

BRINGUP's cloud item said a print is capped by the ring and listed the two
gaps that closed when it stopped being. It now says what bounds a print
(memory, through pulse_reject_threshold_bytes) and what catches a feed that
wedges (progress against room, not ring depth), and it names the two new
cases that cannot be induced from the bench: a body past the memory guard,
because the service has no such job to send, and a wedged feed, because a
healthy machine will not stall on request.

forgectrl.settings-bounds gains a probe at the far end of the new byte
range, so the validator behind those keys is exercised rather than assumed.
This commit is contained in:
ScottW514
2026-08-20 09:23:10 -04:00
parent 0203887dc9
commit e3d23b8099
2 changed files with 24 additions and 9 deletions
+17 -9
View File
@@ -972,15 +972,23 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`.
for them under `/data` on a machine booted into the factory slot before
deciding whether to reimplement the mechanism. Finally the deferred emulator
homing-image smoke, now that the emulator can be pointed at live snapshots.
7. **Cloud mode.** The remaining gaps are tracked in
`python3-gfhardware/forgefirm-app/docs/CLOUD.md` "Outstanding items":
streaming-during-run (would lift the ring-size cap on job length),
oversize-job rejection against a real too-big job, packaged-path boot with
`controller_mode = cloud`, the three unobserved actions, the lid-flash LED,
and taking the pause constants from the pulse header (`CCbp`/`CCbt`) once a
capture confirms them. Not inducible from the bench: the
cancel-with-a-rejected-`settings`-action case and a malformed frame (needs a
MITM). The pulse header's unenforced safety envelope is item 19: it is
7. **Cloud mode.** A print is no longer capped by the ring: the client holds
the compressed body, fills the ring before the button, and tops it up as it
plays, with the body bounded by `pulse_reject_threshold_bytes` because
memory is what that costs. A feed that wedges is caught by progress rather
than by ring depth (a healthy feeder keeps the ring brim-full, so depth
only falls an hour after the feed died): thirty seconds of no progress with
room in the ring stops the job cleanly and retraces, and it resumes if the
feed moves again. The remaining gaps are tracked in
`python3-gfhardware/forgefirm-app/docs/CLOUD.md` "Outstanding items": a
live job longer than the ring (built and covered, never yet run from the
service), the memory guards against a real ceiling rather than a reasoned
one, packaged-path boot with `controller_mode = cloud`, the three unobserved
actions, the lid-flash LED, and taking the pause constants from the pulse
header (`CCbp`/`CCbt`) once a capture confirms them. Not inducible from the bench: the
cancel-with-a-rejected-`settings`-action case, a malformed frame (needs a
MITM), a body past the memory guard (the service has no such job to send),
and a wedged feed (a healthy machine will not stall on request). The pulse header's unenforced safety envelope is item 19: it is
listed separately because the enforcement lands in the cooling engine and
has to hold in GRBL mode too, not only under the cloud client.
8. **Shared machine services — remaining polish.** None of it blocking:
+7
View File
@@ -129,6 +129,13 @@ def settings_bounds(ctx):
ctx.log("POST /settings laser_disarm_s=99999 -> %s", st)
ctx.check(st == 400, "out-of-range value -> %s, expected 400", st)
# The cloud download guard is bytes, so its range is far wider than the
# other numeric keys: check the far end is still a wall.
st, body = fc.post("/settings", data={"pulse_reject_threshold_bytes": "2000000000"})
ev["pulse_bytes_out_of_range"] = st
ctx.log("POST /settings pulse_reject_threshold_bytes=2000000000 -> %s", st)
ctx.check(st == 400, "out-of-range byte limit -> %s, expected 400", st)
st, body = fc.post("/settings", data={"no_such_key_forgetest": "1"})
ev["unknown_key"] = st
ctx.log("POST /settings no_such_key_forgetest=1 -> %s", st)