A yield drop that goes unnoticed for a full shift can mean hundreds of scrapped units. TofuPilot watches first-pass yield on every procedure and notifies you when it falls out of that line's normal range, so you can intervene before the damage spreads.
Why Real-Time Alerting Matters
Production problems rarely announce themselves. A solder paste machine runs low and starts producing weak joints. A fixture contact wears down and adds resistance to every measurement. A new component lot has slightly different characteristics.
In all these cases, the yield drop starts small and grows. The earlier you catch it, the fewer units are affected. Waiting for end-of-shift reports or weekly quality reviews is too slow.
What TofuPilot Can Alert On
TofuPilot monitors your production data and covers six conditions.
| Alert type | What it catches | Automatic |
|---|---|---|
| Yield drop | First-pass yield falls out of the procedure's normal range | Yes |
| Measurement drift | A measurement's mean shifts away from its own baseline | Yes |
| Unit retest threshold | One unit is retested far more than the procedure's norm | Yes |
| Golden sample failed | A known-good reference unit starts failing | Yes |
| Failing sample passed | A known-bad reference unit starts passing | Yes |
| Run failed | A streak of consecutive failed runs | Custom rule only |
The two trend types catch broad degradation. The reference-sample types catch a test that has stopped discriminating at all, which is the failure mode that silently invalidates everything else. Retest thresholds catch the unit nobody wants to admit was retested nine times.
Automatic Detection Sets No Threshold
This is the part most people expect to configure and do not have to.
There is no yield floor to enter. A floor that is right for a line running at 99% is wrong for a burn-in test that normally runs at 55%, and both are healthy. So TofuPilot measures what each procedure normally does — including how much that procedure normally wobbles — and alerts when the current smoothed yield departs from that baseline by more than the line's own variation.
| Severity | Fires at |
|---|---|
| Info | ≥ 2σ |
| Warning | ≥ 3σ |
| Critical | ≥ 5σ |
σ (sigma) here means "multiples of this line's own normal swing". A line that habitually moves between 50% and 60% has a wide normal swing, so wandering inside it does not alert. A line that sits rock-steady at 55% has a narrow one, and the same swing does alert.
Two consequences are worth knowing. A procedure needs roughly 275 first-runs over the past 90 days before automatic yield grading applies, so a brand-new line is silent until it has history. And on near-perfect lines, severity stays at info while fewer than three actual failures sit in recent memory, because above roughly 99.6% yield a single isolated failure is statistically dramatic and practically nothing. The full method is documented in automatic detection.
When to Add a Custom Rule
Automatic detection answers "is this unusual for this line?". A custom rule answers a different question: "is this below the number I promised someone?" Use one when the number comes from outside the data — a customer commitment, a ramp target, a line qualification gate.
Custom yield rules are still expressed as a drop in percentage points against the line's own recent baseline, not as an absolute floor, and you pick which yield they grade:
| Metric | What it counts |
|---|---|
| First Pass Yield | Units whose first-ever run on the procedure passed. Retests cannot improve it. |
| Last Pass Yield | Units whose last run passed. The state after rework. |
| Run pass rate | Passing runs over all runs. Retest storms drag it down fast. |
You set the drop that matters at each severity, and the scope — a whole procedure, one station, one part. See alert rules for the full configuration.
Produce Clean, Structured Test Data
Alerts are only as good as the data behind them. Write your OpenHTF tests with clear, measurable outputs so TofuPilot can track trends and trigger alerts on the right signals.
import openhtf as htffrom openhtf.util import unitsfrom tofupilot.openhtf import TofuPilot@htf.measures( htf.Measurement("charge_voltage") .in_range(minimum=4.15, maximum=4.25) .with_units(units.VOLT), htf.Measurement("charge_current") .in_range(minimum=0.450, maximum=0.550) .with_units(units.AMPERE), htf.Measurement("thermal_shutdown_temp") .in_range(minimum=80, maximum=90) .with_units(units.DEGREE_CELSIUS),)def test_charging_circuit(test): test.measurements.charge_voltage = 4.19 test.measurements.charge_current = 0.498 test.measurements.thermal_shutdown_temp = 85.2def main(): test = htf.Test( test_charging_circuit, station_id="LINE-A-FCT-02", ) with TofuPilot(test): test.execute(test_start=lambda: "CHG-2026-03318")if __name__ == "__main__": main()Each measurement with defined limits feeds TofuPilot's analytics. The tighter and more consistent your naming, the more useful your alerts will be — a measurement renamed halfway through the quarter starts a new series with no history, and a series with no history cannot be graded.
Design Tests for Better Alerting
You can make alerts more useful by how you structure your tests.
import openhtf as htffrom openhtf.util import unitsfrom tofupilot.openhtf import TofuPilot@htf.measures( # Separate measurements for each channel make alerts specific htf.Measurement("led_current_ch1") .in_range(minimum=0.018, maximum=0.022) .with_units(units.AMPERE), htf.Measurement("led_current_ch2") .in_range(minimum=0.018, maximum=0.022) .with_units(units.AMPERE), htf.Measurement("led_current_ch3") .in_range(minimum=0.018, maximum=0.022) .with_units(units.AMPERE), htf.Measurement("led_current_ch4") .in_range(minimum=0.018, maximum=0.022) .with_units(units.AMPERE),)def test_led_channels(test): test.measurements.led_current_ch1 = 0.0201 test.measurements.led_current_ch2 = 0.0198 test.measurements.led_current_ch3 = 0.0203 test.measurements.led_current_ch4 = 0.0200def main(): test = htf.Test( test_led_channels, station_id="LINE-B-FCT-01", ) with TofuPilot(test): test.execute(test_start=lambda: "LED-2026-05519")if __name__ == "__main__": main()Splitting measurements by channel (instead of a single pass/fail for all channels) means TofuPilot can alert you that channel 3 is drifting specifically. That's actionable. A generic "LED test failing more" is not.
Respond to Alerts
When an alert fires, act on it:
- Check the data in TofuPilot. The alert carries the numbers that fired it and a chart of the metric; look at the trend and the distribution to understand what changed.
- Narrow down the scope. Is it one station or all stations? One shift or all shifts? One part or the whole procedure? This points to the root cause faster than any single measurement will.
- Fix the root cause. Recalibrate the equipment, replace the fixture, retrain the operator, quarantine the component lot.
- Let it close itself. A yield alert resolves automatically once the metric recovers well inside the band. Resolving by hand instead snoozes that alert for an hour, which is what you want when you already know and are working on it — and not what you want as a habit.
Alerts are a starting point, not the answer. They tell you something changed. The data in TofuPilot tells you what.