Commit Graph
101 Commits
Author SHA1 Message Date
ScottW514 143ef11a60 forgetest: the liveness test waits for the probe's log line; forgectrl pinned at 0.1.4 (the probe's detail text); the campaign log records the first campaign 2026-09-06 20:57:56 -04:00
ScottW514 8795a6d527 pins: forgectrl, grblHAL-glowforge, and forgefirm-app at the commissioning revisions 2026-09-06 19:56:29 -04:00
ScottW514 97287aa6a9 commissioning: the layer, the acceptance tests, the harness rule, the docs, and the bench drills
meta-forgefirm: the forgefirm-users init replays the account at boot;
sshd refuses root and empty passwords and runs only while the panel
turns it on; the release image keeps an empty root password for the
console; the console banner; avahi announces forgefirm.local; https in
libmicrohttpd and ulfius; the panel on 80 and 443; the license bundle on
the rootfs; release.sh checks the root policy on the built rootfs.

forgetest: the commission suites (commission, commission_dark,
commission_sheet: 23 cases); the runner turns cloud mode on with the
typed phrase for a test that declares it; the baseline's motor_lock is
0; the log-export test checks the bundle for the camera key; the record
helpers write bytes as given and join the daemon's paths as POSIX. The
stream harness gains rule 24: a hold verdict is held again after a
resume. Bench drills: lens_travel.py and lens_stop_accel.py.

Docs: BRINGUP carries the present state; CAMPAIGN-LOG carries the dated
record.
2026-09-06 19:56:05 -04:00
ScottW514 da0299924f pins: forgectrl at the revision the campaign ran
The request-body cap is on the bench. Image 20260904131106 carried
forgectrl ff89288 through a build overlay, and campaign
c-20260904132654-d731 authorized it, 56 of 56.

The pin now says what the campaign ran.
2026-09-04 10:15:02 -04:00
ScottW514 9c6b13e510 pins: the revisions the authorized campaign ran
forgectrl 8ef9509 at 0.1.2, grblhal-glowforge 2f5edee at 0.1.2, and the
forgefirm-app recipes at dd0ebf3, 0.1.23+git. These are the sources the
full campaign on image 20260903211413 passed against, now that their
repositories are pushed and the build no longer needs the local overlay.
2026-09-03 18:12:01 -04:00
ScottW514 05cf7341a4 pins: forgectrl 522cdb2 (0.1.1), grblhal-glowforge b951f3a (0.1.1), forgefirm-app 1511336 (0.1.22+git)
The audit remediation's commits and the bench session's fixes in the
three repositories, pushed and bench-proven on image 20260902144848
(built from the same commits through a local pin overlay). Each PV
moves with its SRCREV; the manifest records the PV.
2026-09-02 19:00:12 -04:00
ScottW514 ef2a8607c2 repos: the sources live in the openglow-org organization
The recipe URLs, the release and install URLs, the vendor check and the CI checkouts name openglow-org, and the grblHAL core fork is openglow-org/grblHAL-core. No catalog change is owed: the recipe edits move the meta-forgefirm content hash, which every test fingerprint folds in through the platform block, so the whole catalog re-runs on its own.
2026-09-01 19:44:47 -04:00
ScottW514 30dba96883 forgectrl: pin 37f4f04 (the supply power-good warning) 2026-09-01 18:50:33 -04:00
ScottW514 a100c9c3eb Pin forgectrl: the crash-watch keys are writable settings 2026-08-31 19:04:35 -04:00
ScottW514 c7c96f9cbe Pin forgectrl: the crash watch; its catalog case and the drill's latch bit
forgectrl 161686f adds the head-accelerometer crash watch (two tiers
on the LIS2HH12's interrupt generators, armed inside the laser's
armed window). The catalog grows cooling.crash-watch-plumbing - the
unarmed half of the watch provable without a button press: accel_watch
stays at watch through an unarmed session, three zeros read as the
three crash gates off, an out-of-range threshold is refused - and
_COOL_COVERS widens to src/accel.*. The armed-tier bench drill is a
BRINGUP next-work item.

The de-risk drill script's CTRL7 write moves from bit 0 (4D_IG1) to
bit 2 (LIR1), the latch the datasheet actually puts there; the drill's
findings did not depend on latching (a continuous gravity signal).
2026-08-31 18:47:49 -04:00
ScottW514 f4de5cdbfd forgetest: the TEC floor relation is the runtime clamp; pin forgectrl
cooling.tec-drive drops its expectation of a settings-level rejection;
the engine's clamp is the enforcement.
2026-08-31 14:55:30 -04:00
ScottW514 c484107779 Pin forgectrl: the start gate is not pinned under the ceiling 2026-08-31 14:41:18 -04:00
ScottW514 78c40ef1ee Pin forgectrl: the HTTP option array carries ulfius' plumbing 2026-08-31 14:26:21 -04:00
ScottW514 e2cf034422 Pin forgectrl: diagnostics as an engine mode, bounded HTTP surface
The item 3 changes ride the pin: the diag take/release contract, the
accept-side connection caps, and the bounded camera setup children.
2026-08-31 14:17:31 -04:00
ScottW514 fe977c0dcc Retire next-work item 1: the fire watch is armed on the bench
The factory-shaped watch is implemented, host-tested and bench-proven
with the lamp as the flame stand-in (CAMPAIGN-LOG has the run, the
fault-class mapping and the recorded interpretation). BRINGUP: the item
closed, items 2 to 18 are now 1 to 17, the references follow, and the
facts bank reads the armed posture. Pin forgectrl for its doc fix.
2026-08-31 13:48:53 -04:00
ScottW514 b506e67bce forgetest: cooling.fire-watch-tiers; pin forgectrl
Both tiers of the factory-shaped fire watch, proven with the lid lamp
as the flame stand-in: a q1 alert under the lamp's reading holds the
session as FLAME and does not survive into a fresh one; a q1 critical
latches FIRE with the laser latch locked; all four thresholds at zero
read as the four flame gates off; restored, the watch reads armed. Pin
forgectrl 77a643441c1c0c745a38aabebc68340d26204ce0 (the watch itself).
2026-08-31 13:23:03 -04:00
ScottW514 6edd3e565c forgetest: cooling.tec-drive; pin forgectrl
The TEC policy at room temperature: declared fitted with its thresholds
under the loop, a run session drives the line on and the session's end
returns it to 0; declared not fitted the line stays 0; the cross-checks
refuse off over on and off under the floor. Pin forgectrl
7d8a58035ca7fadebcae47ea9fd53ef2dd810bac (the TEC drive).
2026-08-31 12:53:16 -04:00
ScottW514 f773866f3e forgetest: the warm-up release comes no earlier than the bulk window
The first bench run released in 15 s on the heater slug; the engine now
judges a one-minute rolling minimum, and the test refuses a release
under 60 s. Pin forgectrl 9d0b757f492281d2628da6800db61a1f490fd125.
2026-08-31 12:27:52 -04:00
ScottW514 a697fe0f63 forgetest: cooling.floor-and-warm-up; pin forgectrl
The catalog case for the two low-side gates: at room temperature the
start gate 1 C above the loop holds the next session in warm-up (heater
on, fans idle, fire blocked) and releases into run at the gate; with the
start gate off, a floor above the loop holds COLD; both at 0 are off and
say so; restored, everything reads as before. Pin forgectrl
5a12f55db6ac632dfc720d9937ca581a7703b7c3 (the gates themselves).
2026-08-31 12:10:11 -04:00
ScottW514 eb8935c9b1 forgetest: aa-offset-calibrate waits for the tool's settle; pin forgectrl
cooling.aa-offset-calibrate gives the tool 540 s (its 420 s stationary
gate plus the six edges) and says so in its steps. Pin forgectrl
7dbb5e1e55a12e6bd1364d920f46c96a3ae2d4ce (the tool settles at the flow
tools' gate before its first edge).
2026-08-31 11:08:45 -04:00
ScottW514 b334c4cc33 image: drop the python3 meta-package and the GnuTLS stack; pin forgectrl and grblHAL
The release rootfs carried python3-modules (tkinter, idle, 2to3, pydoc,
ensurepip, venv, asyncio, multiprocessing, xmlrpc) through the python3
meta-package, and libgnutls30, nettle, libgmp10, libunistring5 and
libtasn1 through libmicrohttpd (https) and ulfius (GnuTLS). Nothing on
the image uses either. Each Python recipe declares the module packages it
imports; forgetest declares its own, so the dev image carries no module
the release image lacks.

Pins: forgectrl 0e907f7db54b7a4c90b660f198d49e5c66b667b5 (armed shown from a
fresh report only, zero smoke phase for a dark session), grblhal-glowforge
fa9ed7834faab6f48367dc1ca5a5109b474f788d (rail enable only standalone).

BRINGUP: the lid IR lamp response measured over the full range; no camera
register file under /data; the rail policy and the cool status items
closed; laser.armed-kill stays in its domain; the debug-kernel drill
constraints.

Platform change (layer content): the full campaign is owed on the built
image.
2026-08-31 09:04:37 -04:00
ScottW514 9a9bb9a47b Pin forgectrl at the ladder-dwell fix 2026-08-30 22:10:01 -04:00
ScottW514 f2b7626d79 Pin forgectrl at the NUL-escape fix 2026-08-30 21:52:18 -04:00
ScottW514 566d836ca0 Pin forgectrl aadf30a and grblhal-glowforge 06965b6
The corner rolloff exponent on the dose curve, and the recorder that
streams its own ladder from one panel press.
2026-08-30 21:48:49 -04:00
ScottW514 5787260a3d Pin forgectrl 10be58c and grblhal-glowforge b54405d
The measured dose curve applied to S (laser_dose_curve, S commands a
light fraction) and the panel's owner-run dose-curve recorder.
2026-08-30 20:28:47 -04:00
ScottW514 557ed02590 Pin forgectrl edaeddd and grblhal-glowforge 09efdc1
The analog dose model's removal: density is the only model, M101 and the
model selection are gone, and the floor derives at every precompute.
2026-08-30 19:44:32 -04:00
ScottW514 67da1ab9bc Pin forgectrl f6698c4 and grblhal-glowforge a1657d7
The M101 dose-model switch with its derived per-model floors, and the
controller's published state files with their /status echo and panel
card. Both proven host-side and, for the switch, on the bench (the
mswitch drill); the catalog covers the changes through the model-aware
laser.power-floor, laser.power-model-switch and the extended
forgectrl.panel-serves.
2026-08-30 16:02:24 -04:00
ScottW514 e32c86fb10 Pin forgectrl 42cdb71; add the coolant offset check; record the compensation on the bench
The pin carries the calibrate tool's sampling fix (3 s at 8 Hz a side).
aa_offset_check.py proves the correction on a machine: M8 brings the fans
to the run profile, dark, while the raw coolant counts, /status and the
engine's readings are averaged before, during and after; it turns the
flow check off for its session and restores it. On the bench page as
aa-offset-check. CAMPAIGN-LOG records the tool's first run, the applied
value (16 counts) and the proof: the readings held within 0.1 C under
the run profile where they dropped 1.0 C uncorrected. BRINGUP item 21
names what remains.

No catalog consequence: a bench tool and records.
2026-08-29 18:02:46 -04:00
ScottW514 5920d9bc77 Pin forgectrl 25cf969 and register the offset probe on the bench page
forgectrl 25cf969 lets status.c link without the cooling engine (the
image build compiles the status host tests), so the pin moves to it;
verified with bitbake -c fetch. offset_probe.py joins the bench-page
registry (survey, ladder and jog; the armed dwell stays a hand-run mode)
and takes "survey" as a mode word.
2026-08-29 17:47:05 -04:00
ScottW514 8831d9b20e Pin forgectrl f9b4893: the air-assist ground shift off the coolant readings
The pin carries the compensation (cool_aa_offset_counts, the
aa-offset-calibrate diagnostic, the panel's Apply); verified with
bitbake -c fetch. The catalog gains cooling.aa-offset-calibrate, which
runs the tool and checks its recommendation and spread.

scripts/bench/offset_probe.py is the differential probe that found the
source: one actuator switched at a time with both sensors at 25 Hz
(survey), the air-assist duty ladder, the gantry jogging under the fan,
and an armed dark dwell. CAMPAIGN-LOG records the four probes and the
result; BRINGUP item 21 names the setting and the calibrate as what
remains on this machine, and item 23 opens the initial commissioning
procedure.

No catalog consequence beyond the new case: a bench tool and records.
2026-08-29 17:36:02 -04:00
ScottW514 d577629c80 Pin grblHAL-glowforge a7dcdca and forgectrl 2f18b16: the arm reads the window, the flow check reads means
grblHAL-glowforge a7dcdca: the arm at the first laser-on is decided by the
window alone, and an RX overrun drops the overrunning line whole and stops
the job. forgectrl 2f18b16: the flow check's baseline and end are means,
and the tube's share of the rise is taken off before the limit. Both
verified with bitbake -c fetch.
2026-08-29 15:01:49 -04:00
ScottW514 4a7d11d48d Pin forgectrl to 78efd16: the loopback peer check in src/peer.c with its unit test 2026-08-24 19:02:52 -04:00
ScottW514 4e79ee5f92 Pin forgectrl to cf8cf1e and grblhal-glowforge to 58b8379: dual-stack listeners, the pstore export 2026-08-24 15:40:19 -04:00
ScottW514 e99888753f forgetest's page moves onto Bootstrap with forgectrl's theme; forgectrl pinned at the panel overhaul
The acceptance page is assembled by page.py from forgetest/forgetest/ui/
(index.html, page.css, help.js, app.js) plus theme.css and the vendored
Bootstrap files, which are byte for byte the ones forgectrl's panel
carries, so the two pages look like one product and share the light and
dark themes (same localStorage key). A plain file is read in a checkout;
on the dev image the recipe installs ui/ gzipped and page.py reads the
.gz sibling, inflating once at first request: the rootfs is raw ext4, so
bytes in the package are bytes on the image. The explanatory prose
(campaign rules, the queues, the campaign actions, the prerequisites
switch, the bench intro) is a "?" popover with a link into the
documentation site; operator steps, prompts, notices and the live-laser
acknowledgment stay in the page, and confirmLive() stays a blocking
dialog. The page's own rules hold: rows, prompt buttons and tool entries
are built once and updated in place, and the popovers sit on static
markup only, so no rebuild orphans one. On a phone the Run pane goes to
the top for the duration of a run.

scripts/check-ui-vendor.py compares the shared files against forgectrl
at its pinned revision (or a local checkout with --forgectrl); it runs
in forgetest-ci.yml, so the copies cannot drift.

Tests: test_page.py (the gzipped install assembles to the same bytes as
a checkout, one self-contained response, the token placeholder once, a
missing marker refused); test_server asserts the served page's
invariants; test_responsiveness keeps its rules with needles pointed at
the new files, its ASCII rule applied to our own sources (Bootstrap's
CSS carries an em dash of its own), and its self-contained rule testing
asset tags rather than the presence of https:// (the documentation links
are meant to be there). forgectrl.panel-serves gains two needles for the
panel's theme attribute and save bar. Proof: the unit suite, and the
page in Chrome against a fake catalog (both themes, popovers, the bench
tab, a full operator run with its prompt, abort).

forgectrl pinned at 9d1f6f2 (the panel on Bootstrap, one save bar, help
popovers, themes, the gzipped page); PV unchanged. The pin moves only
forgectrl's fingerprint. The forgetest changes are the harness's own and
have no catalog consequence.
2026-08-24 12:13:53 -04:00
ScottW514 9887606cfc forgectrl pinned at the browser-proven H.264 view; jog coexistence in the record
The pin moves to forgectrl d97cb35: zero-based fragment timestamps and
the panel's clamped live-edge seek, the two faults MSE playback in a
real browser surfaced. CAMPAIGN-LOG carries the session record,
including the coexistence drill (a jog at commanded feed under both
live streams, underruns unmoved, planner buffer full). BRINGUP item 20
is down to one line: the full acceptance campaign on an image carrying
this pin.
2026-08-24 10:29:01 -04:00
ScottW514 62992fbd7d forgectrl pinned at the two-frame pipeline: ~14 fps on the GPU path
The pin moves to forgectrl deee6a1: the render overlaps the previous
frame' copies and encodes behind an EGL fence, measured 13.8 fps
single-viewer at ~14 percent CPU and 9.8 fps with both stream types
served at once, luma bit-clean throughout. CAMPAIGN-LOG carries the
dated record; BRINGUP item 20 is down to MSE playback, the
coexistence drill, and the campaign.
2026-08-24 09:59:32 -04:00
ScottW514 24dd2b49f6 forgectrl pinned at the 64 ms render; frame skip proven; the record
The pin moves to forgectrl 2d59d78: the chroma passes point-sample
instead of box-averaging, taking the GPU render from 140 ms to 64 and
the stream to ~9 fps at ~7 percent CPU, with luma measured bit-clean
against the CPU path (which also retired the bottom-row artifact).
The CSI hardware frame skip is live-proven with the GPU path and is
the recommended low-CPU configuration. CAMPAIGN-LOG carries the dated
second-session record; BRINGUP item 20 now lists the render-encode
overlap as the path to 15 fps, then MSE playback, the CPU measure,
coexistence, and the campaign.
2026-08-24 09:34:51 -04:00
ScottW514 904dfb4acb forgectrl pinned at the bench-proven GPU path; the session's record
The pin moves to forgectrl 6614833: the five hardware corrections from
the GPU demosaic's first bench session (surfaceless EGL config, ARGB
render targets, GR88 raw import, the ipu_copy stride-fix crop between
the GPU and the CODA, the chroma mirror width). CAMPAIGN-LOG carries
the dated record of how each was found; BRINGUP item 20 now separates
what that session proved (the full GPU -> IPU -> VPU path serving
correct frames, H.264 as valid fragmented MP4 on hardware, texture
limits, slot fit) from what remains (the 140 ms render, the bottom
row, MSE playback, the CPU measurement, frame skip, coexistence, the
campaign).
2026-08-24 09:11:50 -04:00
ScottW514 a47c0c7f6d Video offload: Mesa etnaviv in the image, forgectrl pinned, the H.264 stream in the catalog
The stream conversion now runs on the GC880 when the image carries the
GL stack, and /cam/h264 serves the same picture as fragmented MP4 in a
fraction of MJPEG's bytes (forgectrl 6573abd). This side supplies what
that needs and holds it to account:

- Distro: opengl stays a feature, with mesa trimmed to exactly the
  path used (gallium etnaviv, GLES/EGL/GBM, no GLX, no display
  platforms). Image: libegl-mesa, libgles2-mesa, libgbm,
  mesa-megadriver. forgectrl dlopens them, so an image without them
  still streams on NEON. Platform change: the next campaign is full.
- forgetest: camera.h264-stream exercises the endpoint end to end
  (codec header, init segment, media fragments, /cam/status encoder
  state) and accepts a clean 503 on a machine without the stack;
  the camera covers name the new forgectrl files.
- VIDEO.md 5.6 now describes both streams and why H.264 earns its
  place (the WiFi transmit path measures about 7 percent of the core
  per MB/s sent); BRINGUP records the bench-validation checklist as
  Next work item 20, including the release-size watch: mesa must fit
  the 200 MiB slot gate.
2026-08-24 08:10:33 -04:00
ScottW514 a2b391b8f6 forgectrl pinned at the status-page sys block; panel-serves reads it
The pin picks up /status carrying CPU and memory utilization (sys:
cpu_pct over the interval since the previous read, mem_pct from
MemTotal against MemAvailable) with the panel rows under the board
temperatures. forgectrl.panel-serves now re-reads /status after a
beat and asserts both percents are numbers in range, so the catalog
exercises the new telemetry on the bench.
2026-08-24 07:07:49 -04:00
ScottW514 4e0c90b5a5 The pulse-header envelope settled; the SoC die watched; item 19 closed
forgectrl pin b27398a: the SoC die joins the watched board temperatures
(/status temps soc_c and the kernel's CPU cooling state soc_throttle,
the Status tab, the per-job range line naming a throttle), a throttle
starting or ending is logged, and the supply sensor stays a raw count by
decision (its heatsink cannot be reached with a thermometer while the
machine runs). forgefirm-app pin e65cfc2 (0.1.16+git): every pulse-header
key without an applier is declared with its reason or counted as
undecided in the job log, and CLOUD.md carries one disposition table for
the whole header.

BRINGUP: the pulse-header envelope item is closed. Its durable content is
in the facts bank ("The factory's envelope, decoded": the mandatory tags,
the empty tach windows, the factory's pause and fail tiers, the
per-sensor units, the unarmed flow controller, and ForgeFIRM's answer
with its catalog proofs) and in the "Deliberately not gated" paragraph,
which names every declared family. Item 19 is now the bench-measured
head crash and rail-contact detector; the fire-watch item holds the
header's lid IR thresholds as its prior. The facts bank also records the
SoC's own thermal guard (85 C passive, 90 C critical, no heatsink on the
factory board) and the board temperatures at idle.

Catalog: cooling.gate-off checks the die field, the unthrottled state at
idle and the widened run-end line (the unit fake mirrors it). COOLING
section 9 and the SERVICES verification status describe the present.
2026-08-22 14:24:50 -04:00
ScottW514 6458f6aec0 The ceiling at its off end stands with the default critical line
forgectrl pin 368fd0c: the critical-line cross-check binds only while the
ceiling is a gate. cooling.critical-tier pins that a POST setting the
ceiling to its off end is accepted with the default line (the unit fake
mirrors the exemption); CAMPAIGN-LOG records the gate-off failure on dev
image 20260822165832 that found it, and the critical-tier pass.
2026-08-22 13:43:36 -04:00
ScottW514 9fae47cf14 The critical tier proven on a rising loop; the board temperatures watched
forgectrl pin 76115fd: the chassis LM75 and the supply sensor ride /status
as temps (degrees and a raw count), the engine ranges them over every run
session into one run-end line, and a critical fault that clears with its
session yields the reason to the standing hold.

Bench: critical_tier_drill.py (a bench tool now, registered as
critical-tier) sets the ceiling, the resume gate and the critical line a
few tenths above the live upstream reading and lets the engine's own
flow-check heater warm the loop through them inside one M8 session;
temp_calibrate.py gains supply-watch, supply-point and supply-fit for the
supply sensor against a thermometer on its heatsink, the fit shown beside
UAPI.md's unverified guess.

Catalog: cooling.gate-off checks the /status temps fields and the run-end
board-temperature line (the unit fake mirrors both, one new failure
case); cooling.critical-tier checks the reason after a faulted session.

Docs: CAMPAIGN-LOG entries for cooling.critical-tier on dev image
20260822154257 and the warm-loop drill (OVERTEMP at 10 s, CRITICAL at
14 s, the fault ending with the session); BRINGUP item 19, the facts bank
(board temperatures at idle), COOLING section 9, the bench README.
2026-08-22 12:56:40 -04:00
ScottW514 f51140e528 The coolant critical tier, with its catalog test
forgectrl pin a1875a8: cool_temp_critical_c (default 38 C) is the fail
tier above the coolant ceiling's pause: at or over it in a run session the
verdict is CRITICAL (fire blocked, hold, no resume this job), the fault
ends with the session, the settings API keeps it above the ceiling, and
its top turns the gate off.

Catalog: cooling.critical-tier (auto, 45 tests), driven through the
settings API like cooling.gate-off: a critical line at the ceiling is
refused (and undone should it ever be accepted); with the ceiling, the
resume gate and the critical line all under the coolant's temperature a
session reads CRITICAL rather than OVERTEMP with no resume and the reason
naming the tier and the coolant; after the session the ceiling alone
holds (OVERTEMP); with the critical line at its top the gate is off
(gates_off, the run-start log line) and the ceiling alone pauses;
restored, OK with nothing off. Four unit cases against a scripted engine.
_after_session takes the condition to wait for.

Docs: COOLING (verdict table, section 5, the settings table, the quick
reference), BRINGUP item 19 and the catalog count, the CAMPAIGN-LOG
paragraph for the fan-fault session rule on dev image 20260822145201.
2026-08-22 11:41:18 -04:00
ScottW514 c1591e4f69 The fan floors proven on a pinned image; a fan fault ends with its session
The dated record of dev image 20260822135848: the campaign of every
non-operator, non-live test at 18 of 18 PASS with the measured floors and
the operating-point rule (cooling.fan-gate-trips and the hunt leg of
cloud.mode-switch as recorded), and the unplugged-exhaust-fan drill:
AIRFLOW at the grace plus three ticks with the exhaust dead, the other
fans held, the reason relayed on the Grbl port, the replugged fan ok
inside the next session's grace.

The drill showed the fault riding into idle, where the hold canceled
jogs and would have refused the cloud print that re-proves the fan.
forgectrl pin d51dbdb: the fault ends with its run session, and the next
session judges every fan afresh. cooling.fan-gate-trips checks the
verdict is OK with no hold once the tripped session is over (the unit
fake mirrors it); its covers, and the cooling tests' shared covers, gain
src/coolfmt.* (the tree manifest carries the new files at the bumped pin,
and the lint was right to ask). cloud.mode-switch samples the hunt's gate
rows twice a second: a hunt's run phase is a few seconds long.

Docs: COOLING 3a, BRINGUP item 19, CAMPAIGN-LOG.
2026-08-22 10:46:41 -04:00
ScottW514 adcd1adb9a Fan floors from the measurement; a hunt is measured, not judged
forgectrl pin 47e4256: the airflow floors set from the bench measurement
(exhaust 6400, intake 2290, air assist 6000 rpm, purge current 300, grace
15 s) and the operating-point rule: a fan is judged while the laser is
armed, when a job's profile may raise it but never lower it below the run
duty, or whenever it is commanded at the run duty; the service's hunts,
sent with the extraction fans off, are measured and published unjudged.

Catalog: cloud.mode-switch now waits out the connect-time hunt sampling
/cool/status and requires no AIRFLOW, the exhaust row unjudged and the
exhaust actually off; its covers gain forgectrl src/cool.* and
src/airflow.*. cooling.fan-gate-trips uses an 8 s test grace (the
intakes take 7 s to 90 percent and tripped under the old 2 s at the new
floor) and its off leg waits for the row state as well as gates_off.
fan_floor_measure.py names a reply that is not JSON and calls the purge
readings idle and run (the pump is always on).

Docs: COOLING 3a and the settings table, BRINGUP item 19 and a facts-bank
entry with the measured fan speeds, the bench README, and a CAMPAIGN-LOG
entry for the measurement, the two status-document finds, the hunt find
and the hot-deployed bench runs of both tests.
2026-08-22 09:56:53 -04:00
ScottW514 71a79b6675 Pin forgectrl to the CI-clean airflow commit 2026-08-21 19:05:43 -04:00
ScottW514 0bddc9eeab cooling.fan-gate-trips: a fan under its floor is a fault; pin the airflow gates
The acceptance catalog gains the test behind forgectrl 5a31d66: an
exhaust floor at the legal maximum must trip AIRFLOW after the grace and
three ticks (hold, fire blocked, no resume, the exhaust gate TRIPPED and
named in the reason); a purge current floor at the ADC rail must trip
the same way; an exhaust floor of zero must read off in gates_off and
trip nothing; restored, the next session must run OK with every fan at
or above its floor. Three host cases against a scripted engine that
models the grace and the readings. The covers map names src/airflow.*.

COOLING.md gains 3a (the airflow gates) and the five settings with their
ranges and bands; SERVICES.md the gate rule, the rows, the AIRFLOW
verdict and fan_gates; SAFETY.md names the floors among the verdict's
inputs; BRINGUP item 19 records the gates as in with provisional floors
and the catalog at 44. Pins: forgectrl 5a31d66, forgefirm-app 81027ff
(0.1.15+git); fetch-verified.
2026-08-21 19:00:06 -04:00
ScottW514 5249c1ecf8 CAMPAIGN-LOG: the job's limits pass through on a live session
cloud.pause-resume passed on dev image 20260821220926 with the service's
hunt windows (10 to 50 C) ignored as looser and the print's window (33 C,
5 C floor, 116 rpm air-assist floor) matched. The test now quotes the
print's job-limits line rather than the session's first (a hunt's), and
keeps the engine line that carries the header beside the last one.
forgectrl pin moves to e0b41b3 (the "not stricter" notice once per value).
2026-08-21 18:39:43 -04:00
ScottW514 d530f773e2 cloud.pause-resume reads the job's limits through; pin the pass-through
The pulse header's envelope now reaches the cooling engine: the cloud
client (python3-gfhardware c34faa1) derives the coolant window and the
fans' minimum speeds from the header and rides them on every report,
and the engine (forgectrl 57f6064) resolves each as the stricter of its
setting and the job's, never looser and never overruling an off gate.
cloud.pause-resume, which runs a real print, now also reads the client's
"job limits from the header:" line and the engine's "effective limits:"
line from the two logs; two host cases cover the failure paths. The
needle guard lists the engine's phrases as not the app's.

COOLING.md section 2 explains what a cloud job brings with it; BRINGUP
item 19 records the pass-through as landed. Pins: forgectrl 57f6064,
forgefirm-app c34faa1 (0.1.14+git); fetch-verified.
2026-08-21 18:07:41 -04:00