mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-28 09:11:11 -07:00
cooling.gate-off: a gate setting trips in range and is off at its far end
The acceptance catalog gains the test behind forgectrl 9e44fdc: the coolant ceiling set just over its legal minimum must trip OVERTEMP with a hold and fire blocked at the next run start; set to its top the engine must skip the gate (verdict OK), report it in gates_off on /status and /cool/status, and log the run-start line; the original values are restored, on failure too, and proven restored. Five host cases against a scripted engine. The cooling covers map now names the files that carry gate state (gates, settings, status, the panel) and corrects a glob that matched nothing: the GRBL cooling client is src/glowforge_cooling.c, not src/gfcool*. The fake forgectrl serves /logs/tail and keeps blank form values as "clear", which is what the daemon does with them. Docs: COOLING.md section 8 carries each setting's legal range and recommended band and a new 8a on turning a gate off; SAFETY.md names what no setting can reach; ACCEPTANCE.md records that gates are exercised through the settings API, never GFCOOL_* env overrides; BRINGUP item 19 records the pattern as landed and the catalog is 43. forgectrl pin moves to 9e44fdc; fetch-verified.
This commit is contained in:
@@ -235,6 +235,11 @@ tests:
|
||||
2. does that test's `covers` map name the files touched - if not, widen it
|
||||
in the same change.
|
||||
|
||||
A gate or a limit is exercised through the settings API (a value a healthy
|
||||
machine cannot meet, re-read by the engine at the next run start, restored
|
||||
by the test's own teardown), never through `GFCOOL_*` environment overrides,
|
||||
which need a daemon restart and stay bench-only.
|
||||
|
||||
A behavior change with no catalog consequence needs a sentence of
|
||||
justification in the commit message. Coverage gaps are defects: under the
|
||||
domain model an uncovered path lets an inherited PASS stay valid across a
|
||||
|
||||
+16
-3
@@ -48,7 +48,7 @@ hardware-validated.**
|
||||
modes (cancel-and-return on a lid or interlock open, button pause/resume),
|
||||
bench-validated 2026-08-17.
|
||||
- **Releases are gated by the acceptance tool** (`forgetest`, dev image only):
|
||||
a 42-test catalog, domain-scoped inheritance, an always-required safety core,
|
||||
a 43-test catalog, domain-scoped inheritance, an always-required safety core,
|
||||
and a release gate that reads the exported artifact. The full campaign on
|
||||
dev image `20260821181036` (the first built on the `<recipe>-pin.inc`
|
||||
layout) satisfied 42 of 42 and its export authorizes a release;
|
||||
@@ -579,12 +579,13 @@ under the domain model from the day's earlier dev images) and the export reads "
|
||||
YES" for that image's manifest. That authorizes a release; it is not one
|
||||
until `releases/v<version>/acceptance.json` is committed.
|
||||
|
||||
- **Catalog: 42 tests** in `forgetest/forgetest/suite/`, every one a port of a
|
||||
- **Catalog: 43 tests** in `forgetest/forgetest/suite/`, every one a port of a
|
||||
proven bench drill or a bench-verified check — the always-required core
|
||||
(`image.health`, `kernel.latch-locked-idle`, `kernel.k1-k2`,
|
||||
`kernel.fire-line`), `forgectrl.*`, `logs.*`, `update.*`, `motion.*`
|
||||
(pacing, jog round-trip, liveness probe, cancel/abort, dead-man, the lid,
|
||||
interlock and button parity tests), `cooling.*`, `camera.snapshot`,
|
||||
interlock and button parity tests), `cooling.*` (flow verification, fans
|
||||
quiet after motion, a gate setting tripping and off by value), `camera.snapshot`,
|
||||
`laser.*` (emission witness, arm-wait lid, disarm-in-hold, armed kill,
|
||||
pause/resume/lid-cancel) and `cloud.*`. Tests that share a setup are merged;
|
||||
the `auto` tests stay separate for failure isolation.
|
||||
@@ -1314,6 +1315,18 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`.
|
||||
data format, both checked before a byte reaches the ring) and drops the
|
||||
rest. Seventeen of the mandatory ones are among the dropped.
|
||||
|
||||
**Landed first, the pattern every gate ships on:** a gate is a plain
|
||||
setting with a wide legal range, a recommended band, and an off end (a
|
||||
ceiling at its maximum, a window of zero) that turns the gate off by
|
||||
value, with no separate switch; the panel warns outside the band and
|
||||
while any gate is off, the engine logs each gate setting at every run
|
||||
start, `/status` and `/cool/status` carry `gates_off`, and an off gate
|
||||
keeps measuring. Applied to the coolant ceiling, its resume gate, the
|
||||
flow window and the flow rise (`forgectrl/src/gates.c`, `SERVICES.md`
|
||||
"Gate settings", `COOLING.md` §8a, `cooling.gate-off` in the catalog).
|
||||
The fan gates, the pass-through of header limits, the coolant critical
|
||||
tier and the watch-only board temperatures follow on it.
|
||||
|
||||
Nothing here can put energy where it was not commanded: the hardware chain
|
||||
is the emission boundary and no header field touches it, and forgectrl runs
|
||||
its own coolant ceiling, flow verification, emission witness, liveness gate
|
||||
|
||||
+37
-12
@@ -300,25 +300,49 @@ All of these live in the panel's Machine tab, are validated on entry, and can
|
||||
only be changed while the machine is idle. The engine re-reads them at the
|
||||
start of every run, so a change takes effect on your next job.
|
||||
|
||||
| Setting | Default | What it controls |
|
||||
|---|---|---|
|
||||
| `cool_flow_rise` | 14.4 °C | Downstream rise that counts as no-flow. Set this from **flow calibrate**. |
|
||||
| `cool_flow_heater_pct` | 40 % | Heater duty during a check. Raising it separates the bands further at the cost of warming the loop more. |
|
||||
| `cool_flow_check_s` | 50 s | Length of a check window. `0` disables flow verification entirely. |
|
||||
| `cool_recheck_s` | 150 s | How often checks repeat during a job. |
|
||||
| `cool_confirm_max_s` | 480 s | How long a suspicion may stay unresolved before it escalates to a fault. |
|
||||
| `cool_temp_max` | 33 °C | Run ceiling — above it, hold. |
|
||||
| `cool_temp_resume` | 31 °C | Resume gate — below it, continue. |
|
||||
| `cool_cooldown_s` | 15 s | Smoke-clear phase at run duty after a job. |
|
||||
| `cool_cooldown_max_s` | 300 s | Cap on the thermal cooldown phase. |
|
||||
| Setting | Default | Legal range | Recommended | What it controls |
|
||||
|---|---|---|---|---|
|
||||
| `cool_flow_rise` | 14.4 °C | 1 to 40 °C | 8 to 16 °C | Downstream rise that counts as no-flow. Set this from **flow calibrate**; above the band the check can never fault. |
|
||||
| `cool_flow_heater_pct` | 40 % | 0 to 100 % | | Heater duty during a check. Raising it separates the bands further at the cost of warming the loop more. |
|
||||
| `cool_flow_check_s` | 50 s | 0 to 300 s | 30 to 120 s | Length of a check window. `0` turns flow verification off (§8a). |
|
||||
| `cool_recheck_s` | 150 s | 0 to 3600 s | | How often checks repeat during a job. |
|
||||
| `cool_confirm_max_s` | 480 s | 60 to 3600 s | | How long a suspicion may stay unresolved before it escalates to a fault. |
|
||||
| `cool_temp_max` | 33 °C | 5 to 60 °C | 25 to 38 °C | Run ceiling: above it, hold. `60` turns the gate off (§8a). |
|
||||
| `cool_temp_resume` | 31 °C | 5 to 59 °C | 20 to 36 °C | Resume gate: below it, continue. Always kept below the ceiling. |
|
||||
| `cool_cooldown_s` | 15 s | 0 to 1800 s | | Smoke-clear phase at run duty after a job. |
|
||||
| `cool_cooldown_max_s` | 300 s | 0 to 1800 s | | Cap on the thermal cooldown phase. |
|
||||
|
||||
Two settings are deliberately not on the panel:
|
||||
|
||||
- `cool_fire_ir_delta` — the lid-IR fire gate (§7). It is `0`, watch-only, and
|
||||
- `cool_fire_ir_delta`, the lid-IR fire gate (§7). It is `0`, watch-only, and
|
||||
changing it by hand is not recommended until the watch is lamp-aware.
|
||||
- `GFCOOL_*` environment overrides exist for bench work; they win for the
|
||||
lifetime of the process and are not a normal operating path.
|
||||
|
||||
### 8a. Turning a gate off
|
||||
|
||||
The gates are settings, and the far end of a gate setting's range is the off
|
||||
switch: a coolant ceiling of 60 °C never trips, and a check window of 0 s runs
|
||||
no flow verification at all. There is no other switch, and no list of names to
|
||||
get wrong. The ranges are wide on purpose: the shipped defaults and the
|
||||
recommended bands come from one bench machine, and a machine whose loop or
|
||||
sensors read differently changes the number rather than waiting for new
|
||||
firmware.
|
||||
|
||||
A gate that is off is not a gate that is forgotten. The panel flags any value
|
||||
outside its recommended band beside the field and says "this gate is OFF" at
|
||||
the far end; the Status tab shows a standing banner while any gate is off; the
|
||||
engine logs one line per gate setting at every run start, and with the ceiling
|
||||
off it still logs the first reading in a job that would have tripped the
|
||||
default. `/status` and `/cool/status` carry the off gates as `gates_off`.
|
||||
Nothing about it reaches the cloud service.
|
||||
|
||||
What no setting can reach: the hardware safety chain, the laser latch, the
|
||||
emission witness, the lid-IR fire watch, the controller-silence dead-man, and
|
||||
the motion-liveness gate. A machine with every thermal gate off still stops
|
||||
firing the moment its controller goes quiet; what it no longer does is hold a
|
||||
job for a stopped pump or an overheating loop. The banner says so.
|
||||
|
||||
---
|
||||
|
||||
## 9. Not implemented yet
|
||||
@@ -348,6 +372,7 @@ Stated plainly so nobody counts on them:
|
||||
| Suspicion unresolved past the budget | Escalates to `FAULT`. |
|
||||
| Three cleared suspicions in one job | Aggregated "check your coolant" warning. |
|
||||
| Upstream coolant above 33 °C | `OVERTEMP`: hold + forced cooling; auto-resume under 31 °C. |
|
||||
| A gate setting at its off end (ceiling 60 °C, check window 0 s) | No verdict from that gate; a run-start log line, `gates_off` in `/status`, and a standing panel banner. |
|
||||
| Job ends | 15 s smoke clear at run duty, then reduced airflow until the loop is under the resume gate. |
|
||||
| Controller stops reporting | Fire blocked at once, stand-down through cooldown. |
|
||||
| Silence while armed, or a program still playing | Motion stopped and the latch locked by the engine itself. |
|
||||
|
||||
+5
-1
@@ -205,7 +205,11 @@ would not allow.
|
||||
finish the queue tail so a controlled stop can never leave FIRE driven.
|
||||
- **Coolant fire gates.** The armed window requires a fresh `fire_ok` verdict
|
||||
from the cooling engine (flow verification, over-temperature, lid-IR
|
||||
emission witness); a stale or failed verdict relocks in-process.
|
||||
emission witness); a stale or failed verdict relocks in-process. The
|
||||
thermal gates are settings with a wide range whose far end turns the gate
|
||||
off by value (`COOLING.md` §8a), loudly; the fresh-report rule, the
|
||||
emission witness, the dead-man and the latch are not settings and stay in
|
||||
force whatever the gates are set to.
|
||||
- **Safety door.** `doors` (lid) and `interlock` (loop open) are the core's
|
||||
safety-door signal, shown to the core only while it is in a job-time state
|
||||
(cycle, hold, tool change, door): a running job parks with a planned
|
||||
|
||||
Reference in New Issue
Block a user