Operator fault panel: separate a unit fault from a station fault - #31
Merged
Conversation
An ordinary DUT rejection ends a test with OpenHTF's own bare STOP detail
("Phase X stopped the test run"), which named no measurement and offered the
panel's "unexpected error — notify Halter" button. Operators pressed it: 68% of
the fault reports reaching #htf-error-unbind over 2026-08-31 were yield loss,
burying the plug-init errors the channel exists to surface.
Two new GUI-only fields on OutcomeDetails carry the distinction, both stripped
from shipped JSON reports by the framework's output callback:
- notifiable — false means "show the message, offer no button". A DUT that
failed a measurement is not something to page anyone about.
- catalogue_code — the catalogue entry a detail's text came from, when it
differs from the detail's own code. Shown under the code so an engineer can
find the entry to edit.
Panel changes for a non-notifiable detail: the spec list is rendered above the
remediation rather than de-emphasised below it (the operator's decision is about
the part in hand), the notify and escalate buttons are suppressed, the header
reads UNIT DID NOT MEET SPEC, and the de-emphasised Issue block keeps only the
code. A station fault renders exactly as before.
The serial and each failing measurement name are bolded. Both are found
structurally — the DUT id by string match, the name as whatever precedes ' = '
on a ' - ' line — because the text is bilingual and no markup may go in the
description, which reaches the JSON report and Athena.
Every panel stays red. An orange variant for the unit case was built and
removed: the panel means the test failed either way, and what actually differs
is whether the operator is asked to alert anyone, which the header wording and
the absent button already carry.
Coverage Report for CI Build 33558513976Coverage increased (+0.01%) to 60.622%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Jwnadler
approved these changes
Sep 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
An ordinary DUT rejection ends a test with OpenHTF's own bare
STOPdetail — "Phase X stopped the test run" — which names no measurement and carries no remediation. The operator panel therefore showed it as an unexpected error with a Notify Halter button, which is the only thing it could do with a detail it had no text for.Operators pressed it. Over 2026-08-31, 27 of the 40 fault reports reaching
#htf-error-unbind(68%) were yield loss, and that volume buried the two reports that mattered: a plug-initValueErrorand a collar with no battery bound.The panel had two states — has remediation, or does not. It needed a third: has remediation, and nobody should be notified.
What
Two GUI-only fields on
OutcomeDetails, both stripped from shipped JSON reports by the framework's output callback so the Manufacturing Service / Athena payload keeps its shape:notifiable—Falsemeans show the message and offer no button.catalogue_code— the catalogue entry a detail's text came from, when it differs from the detail's own code. Rendered under the code so an engineer can find the entry to edit.For a non-notifiable detail the panel:
TEST FAILED — UNIT DID NOT MEET SPECin the header;A station fault renders exactly as before.
The serial and each failing measurement name are bolded. Both are found structurally — the DUT id by string match, the name as whatever precedes
' = 'on a' - 'line — rather than by parsing prose: the panel text is bilingual, and no markup may go into the description, which reaches the JSON report and Athena.Decisions worth recording
Every panel stays red. An orange variant for the unit case was built and then removed. The panel means the test failed either way; what actually differs is whether the operator is being asked to alert anyone, and the header wording plus the absent button already carry that. A second colour would need to encode something those two do not.
<pre>became onedivper line so the emphasis can be applied — andwhite-space: pre-wrapmoved onto the line, not the container. On the container it also preserves the template's own indentation between the block elements, which renders as a blank line between every entry.The bullet shape is a cross-repo contract.
' - NAME = value'is produced byfault_catalog._failing_measurementsin hardware-test-framework and matched byspecLineshere. Changing either side stops the emphasis silently rather than breaking — the intended failure mode, but worth knowing. Nothing tests the two halves against each other yet; the repo has no front-end test tier in use.dist/web_gui_server.py:30servesweb_gui/dist, and stations have neither node nor npm — no build step exists in the framework's ansible roles or tarball script. So the built bundle is committed, as it always has been: 8 deletions, 8 additions, oneindex.htmlchange, a single bundle (app.484afc41…).Verification
Driven through the real
run_test_loopon hq-1500 — a measurement fail, a mapped phase timeout and an unmapped one. Checked the panel payload over the station's own websocket, theFAULT_OCCURRENCElines, and the shipped JSON report keeping its pre-change key set.The fork's own test suite was not run: the framework's CI only runs
hardware_test_framework/unittests. Existing tests constructingOutcomeDetailspositionally are unaffected — both new fields default.Paired with the hardware-test-framework PR that consumes these fields.