UI/HDTFailure.xaml

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Hephaestus Deployment Toolkit"
    WindowStyle="None"
    ResizeMode="NoResize"
    SizeToContent="WidthAndHeight"
    WindowStartupLocation="CenterScreen"
    Background="#FF1E1E1E">
 
    <!--
        WHAT A TECHNICIAN SEES WHEN A DEPLOYMENT FAILS, and until now that was
        nothing: the reason went into the JSONL, a FATAL line went into a
        console the payload had hidden, and five seconds later wpeutil powered
        the machine off. Everything needed to fix it was on a share, under a
        folder named after a computer that never finished being built.
 
        MDT SHOWS A SUMMARY DIALOG NAMING THE STEP, and an admin has read it a
        hundred times. This is that, in HDT's ground.
 
        THE MACHINE DOES NOT POWER OFF WHILE THIS IS UP. The three buttons are
        the three things a technician actually does next, and the payload obeys
        whichever was pressed: go and look (Open CMD), try again from the top
        (Restart), or leave (Shut down).
 
        SAME GROUND AS THE WIZARD AND THE PROGRESS SCREEN. A technician meets
        all three on one machine minutes apart, and they must look like one
        product: #FF1E1E1E behind, #FF252526 on the card.
 
        NOT Topmost, AND A TECHNICIAN AT A BENCH IS WHY. This window used to
        carry Topmost="True", and the cost of it was the one button on the
        screen that matters: Open CMD (and F8) launched the command prompt
        CORRECTLY and it opened BEHIND this window, where it could not be seen,
        clicked, or reached. A topmost window outranks any non-topmost
        foreground window, so the prompt was not merely unfocused - it was
        unreachable, on the screen whose entire purpose is to hand a broken
        machine back to a human being who can look inside it.
 
        AND IT BOUGHT NOTHING IN RETURN. In WinPE there is no shell, no taskbar
        and no other application: there is nothing for this window to lose
        itself behind, which is exactly why the attribute was never noticed.
        HDTProgress.xaml keeps its Topmost for the opposite reason - that board
        outlives WinPE and draws on a real desktop, where a Start menu opens
        over it - and Start-HDTDeployment closes it before any prompt can be
        opened, so it never stands in front of one.
 
        TOPMOST IS STATE, NOT MARKUP. A window that hands the machine to
        another process has to stop outranking it, and an attribute cannot.
        tests/contract/WinPeWindowReach.Contract.Tests.ps1 holds the rule for
        every window in this folder.
 
        AND THE REFERENCE IMPLEMENTATION SAYS THE SAME, WHICH IS WHY THIS IS A
        RULE AND NOT ONE BENCH'S OPINION. friendsOfMDT/PSD - MIT licensed,
        NOTICE.md - clears Topmost on the line before EVERY ShowDialog, under
        its own comment "always force windows on bottom"
        (Scripts/PSDWizardNew.psm1:760 and :2995,
        Scripts/PSDStartLoader.psm1:2780), binds Esc to lower the window
        (PSDWizardNew.psm1:2764-2767), and where it does raise a window it
        drives it from a runtime flag rather than markup
        (PSDStartLoader.psm1:2352). What was derived is that mechanism, not
        code: HDT deletes the attribute instead of assigning the property,
        because a window that never outranks the prompt has nothing to undo.
 
        NO x:Class AND NO MERGED DICTIONARY: there is no compiler in WinPE, and
        a second file that must reach the RAM disk intact is a
        XamlParseException on the one machine nobody can debug.
    -->
 
    <Grid Background="#FF1E1E1E">
 
        <Border Width="900" VerticalAlignment="Center" HorizontalAlignment="Center"
                Background="#FF252526" BorderBrush="#FF3A3A3C" BorderThickness="1">
            <StackPanel Margin="36,30,36,30">
 
                <!--
                    ============ the grab handle ============
 
                    THE HEADLINE IS WHAT YOU DRAG THE WINDOW BY. WindowStyle=
                    "None" is right here - an X on a failure screen is a fourth
                    answer nobody meant to give - but it takes the title bar
                    away, and with it the thing a hand reaches for. A technician
                    in front of a failed machine could not move this window at
                    all: not off a log they wanted to read behind it, not out of
                    the way of a command prompt.
 
                    New-HDTWizardHost wires DragMove onto whatever is named
                    HDTDragBanner and onto nothing else, and its lookup is
                    null-guarded - so a window without one does not fail, log or
                    warn. It is simply immovable, which is precisely how this
                    screen shipped that way and why the rule now lives in
                    tests/contract/WinPeWindowReach.Contract.Tests.ps1 rather
                    than in one file's memory. The wizard shell, the welcome
                    screen and both credential pages have carried the same
                    named Border since they were written; this is that.
 
                    IT NEEDS A GROUND TO BE GRABBED AT ALL. A Border with no
                    Background is invisible to hit-testing in WPF, and so is a
                    TextBlock - the mouse would go straight through the headline
                    to the card behind it and no drag would ever start. So it
                    paints the card's own #FF252526: the same colour that was
                    already there, which is why nothing about this screen looks
                    different. No padding, no margin, no border thickness -
                    the three lines below sit exactly where they sat.
 
                    THE BUTTONS ARE OUTSIDE IT, deliberately. A banner that
                    covered Open CMD would answer a click by moving the window
                    instead of opening the prompt, which is the same defect in a
                    new coat.
                -->
                <Border x:Name="HDTDragBanner" Background="#FF252526">
                    <StackPanel>
 
                        <!--
                            RED, ONCE, AT THE TOP. The status line on the
                            progress screen paints failures #FFF48771 and so
                            does this: the same colour means the same thing
                            across the product.
                        -->
                        <TextBlock x:Name="HDTFailureTitleText" Foreground="#FFF48771"
                                   FontSize="28" FontWeight="SemiBold" />
 
                        <!--
                            AND THE SAME WINDOW REPORTS A RUN THAT WORKED,
                            because MDT ends a deployment on ONE Deployment
                            Summary rather than two windows to keep in step with
                            each other.
 
                            TWO HEADLINES, ONE VISIBLE. The colour is the whole
                            reason this is a second TextBlock instead of one line
                            of text that changes: #FFF48771 is what failure looks
                            like everywhere in this product, and a success
                            painted in it reads as a failure that somebody
                            mislabelled. Red only ever means wrong.
 
                            Which one shows is a Pane flag, the mechanism the
                            host already has - Get-HDTDeploymentFailure decides,
                            and this file only says what the two look like.
                        -->
                        <TextBlock x:Name="HDTFailureSuccessText" Foreground="#FF6FCF97"
                                   FontSize="28" FontWeight="SemiBold"
                                   Visibility="Collapsed" />
 
                        <TextBlock x:Name="HDTFailureSequenceText" Text="" Foreground="#FFCCCCCC"
                                   FontSize="15" Margin="0,6,0,0" TextTrimming="CharacterEllipsis" />
                    </StackPanel>
                </Border>
 
                <Border Height="1" Background="#FF3A3A3C" Margin="0,20,0,20" />
 
                <!-- ============ which step ============ -->
                <TextBlock x:Name="HDTFailureStepLabel" Foreground="#FF8A8A8A" FontSize="13" />
                <TextBlock x:Name="HDTFailureStepText" Text="" Foreground="White"
                           FontSize="18" Margin="0,4,0,0" TextWrapping="Wrap" />
 
                <!-- ============ and why ============ -->
                <!--
                    THE REASON IS NOT SUMMARISED AND IT SCROLLS. The pre-flight
                    writes several lines - one per failed check - and the most
                    useful sentence a technician can read is the one the step
                    wrote: "disk 0 carries existing data on volume C (NTFS), D
                    (NTFS), and the step did not declare that it may be
                    replaced" contains the fix. A box that cut it off at one
                    line would send them to the log for the rest.
                -->
                <TextBlock x:Name="HDTFailureReasonLabel" Foreground="#FF8A8A8A" FontSize="13" Margin="0,18,0,0" />
 
                <Border x:Name="HDTFailureReasonBox"
                        Background="#FF1E1E1E" BorderBrush="#FF3A3A3C" BorderThickness="1"
                        Margin="0,4,0,0" MaxHeight="220">
                    <ScrollViewer VerticalScrollBarVisibility="Auto" Padding="12,10,12,10">
                        <TextBlock x:Name="HDTFailureMessageText" Text="" Foreground="#FFF48771"
                                   FontSize="14" TextWrapping="Wrap"
                                   FontFamily="Consolas, Courier New" />
                    </ScrollViewer>
                </Border>
 
                <!-- ============ where the evidence is ============ -->
                <!--
                    THE LOG PATH IS ON THE SCREEN BECAUSE X: DIES WITH THE
                    POWER. A technician who writes nothing down and shuts the
                    machine off must still be able to find the run afterwards,
                    and the run id is what names the folder.
                -->
                <TextBlock x:Name="HDTFailureLogLabel" Foreground="#FF8A8A8A" FontSize="13" Margin="0,18,0,0" />
                <TextBlock x:Name="HDTFailureLogText" Text="" Foreground="#FFCCCCCC"
                           FontSize="13" Margin="0,4,0,0" TextWrapping="Wrap"
                           FontFamily="Consolas, Courier New" />
                <TextBlock x:Name="HDTFailureRunText" Text="" Foreground="#FF8A8A8A"
                           FontSize="12" Margin="0,4,0,0" FontFamily="Consolas, Courier New" />
 
                <!-- ============ what happens next ============ -->
                <!--
                    THE SAME THREE NAMES THE WIZARD USES, so the host that
                    already knows how to read a window can read this one:
                    HDTOpenCmdButton, HDTNextButton, HDTCancelButton.
 
                    OPEN CMD IS FIRST ON A FAILURE because that is the reason
                    the failure screen exists - the technician is standing in
                    front of a machine they can still look inside.
 
                    AND IT IS COLLAPSED ON A SUCCESS, by the same Pane list
                    that collapses Restart and Shut down: a machine that
                    finished has nothing left to diagnose, and the summary
                    offers Finish alone. The '*' column beside it absorbs the
                    space, so Finish stays in the corner either way. F8 still
                    opens a prompt on both - a key nobody can see is not
                    clutter.
                -->
                <Grid Margin="0,28,0,0">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
 
                    <Button Grid.Column="0" x:Name="HDTOpenCmdButton"
                            MinWidth="130" Height="36" Background="#FF3A3A3C" Foreground="White"
                            BorderBrush="#FF3A3A3C" FontSize="14" />
 
                    <Button Grid.Column="2" x:Name="HDTCancelButton"
                            MinWidth="130" Height="36" Margin="0,0,10,0"
                            Background="#FF3A3A3C" Foreground="White"
                            BorderBrush="#FF3A3A3C" FontSize="14" />
 
                    <Button Grid.Column="3" x:Name="HDTNextButton"
                            MinWidth="130" Height="36"
                            Background="#FF0E639C" Foreground="White"
                            BorderBrush="#FF0E639C" FontSize="14" />
 
                    <!--
                        MDT'S DEPLOYMENT SUMMARY HAS ONE BUTTON AND IT IS
                        Finish. This window reports both outcomes, so it carries
                        both sets and Get-HDTDeploymentFailure collapses the pair
                        that does not apply: Restart and Shut down on a failure,
                        this on a finished machine.
 
                        IT SHARES A COLUMN WITH Restart, which is why only one
                        of them is ever visible. Two primary buttons in one
                        corner is a screen asking a technician which of two
                        identical-looking things they meant.
 
                        WHAT HAPPENS AFTERWARDS IS NOT THIS BUTTON'S ANSWER.
                        HDTFinishAction owns that - MDT's property, MDT's
                        meaning - and this only says the technician has read the
                        screen. Restart and Shut down override it, because a
                        button naming a power state and not producing it is
                        worse than no button.
                    -->
                    <Button Grid.Column="3" x:Name="HDTFinishButton"
                            MinWidth="130" Height="36"
                            Background="#FF0E639C" Foreground="White"
                            BorderBrush="#FF0E639C" FontSize="14"
                            Visibility="Collapsed" />
                </Grid>
            </StackPanel>
        </Border>
    </Grid>
</Window>