BT410 5.3.132: the watchers finally see something -- every watch link in the mech gets bound, and the gyro's complaint narrows to a brownout

The gap found in 5.3.131 is closed.  HeatWatcher has always streamed a
watchedSubsystem index and read it into a member; nothing ever turned it
into the link UpdateWatch resolves, so the entire watcher family --
PowerWatcher and the Gyroscope / Torso / HUD / AmmoBin leaves included --
resolved NULL and reported its target dead.

The Mech ctor now binds them in a post-walk pass, which is where it has
to be: a watcher may legally watch a subsystem with a higher roster id,
which does not exist yet while the segment walk is still building.
Out-of-range and self-referencing indices are skipped rather than
trusted.

THE BINDINGS PROVE THEMSELVES -- every index lands on a semantically
right target, which a wrong offset could not manage:

    Gyroscope      -> Avionics       Torso          -> Myomers
    HUD            -> Avionics       Searchlight    -> Avionics
    AmmoBinAFC100  -> AFC100         AmmoBinLRM15_1 -> LRM15_1
    AmmoBinLRM15_2 -> LRM15_2

The gyro and HUD watch the avionics bus, the torso watches the muscles
that move it, and every ammo bin watches its own gun.

With the link live the gyro's watchdog moved off the NULL fallback (0 ->
1) but has not reached Ready.  UpdateWatch can produce 1 two ways --
NoVoltage, or a brownout on a target that IS ready -- and since Avionics
is a Sensor reporting voltState 4, the brownout branch is the suspect.
Recorded as the next question with the experiment that separates the two
causes, rather than quieting an alarm by moving a threshold.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-08-10 08:22:43 -05:00
co-authored by Claude Fable 5
parent 4ad97b5d41
commit 453fa0ecee
3 changed files with 103 additions and 0 deletions
+20
View File
@@ -259,6 +259,26 @@
protected:
SubsystemConnection watchedLink;
public:
//
// THE WATCH BIND (5.3.132). The streamed `watchedSubsystem` index
// has been read since this class landed, but nothing ever turned it
// into the link `UpdateWatch` resolves -- so every watcher in the
// mech resolved NULL and reported its target dead. The Mech ctor
// binds these in a post-walk pass: a watcher can legally watch a
// subsystem with a HIGHER roster id, which does not exist yet while
// the segment walk is still building, so the bind cannot live in
// this ctor.
//
int
WatchedSubsystemIndex() const
{ Check(this); return watchedSubsystem; }
void
BindWatchedSubsystem(Subsystem *watched)
{ Check(this); watchedLink.Add(watched); }
protected:
int watchedSubsystem;
Scalar degradationTemperature;
Scalar failureTemperature;
+45
View File
@@ -598,6 +598,51 @@ Mech::Mech(
}
RedistributeCoolantShares();
//
//-----------------------------------------------------------------------
// THE WATCH BINDS (5.3.132). Every HeatWatcher descendant -- which is
// the whole watcher family, PowerWatcher and the Gyroscope / Torso / HUD
// leaves included -- streams the roster index of the subsystem it
// watches, and `UpdateWatch` resolves a link built from it. Nothing
// ever built that link, so every watcher resolved NULL and reported its
// target unpowered / stone cold.
//
// This runs POST-WALK, not in the watcher ctor: a watcher may legally
// watch a subsystem with a higher roster id, which does not exist yet
// while the walk is still building. Out-of-range and self-referencing
// indices are skipped rather than trusted.
//-----------------------------------------------------------------------
//
{
for (int wb = 2; wb < subsystemCount; ++wb)
{
Subsystem *watcher = subsystemArray[wb];
if (
watcher == NULL ||
!watcher->IsDerivedFrom(HeatWatcher::ClassDerivations)
)
{
continue;
}
int index = ((HeatWatcher *)watcher)->WatchedSubsystemIndex();
Subsystem *watched =
(index >= 2 && index < subsystemCount && index != wb)
? subsystemArray[index]
: NULL;
((HeatWatcher *)watcher)->BindWatchedSubsystem(watched);
if (getenv("BT_MECH_LOG"))
{
DEBUG_STREAM << "[watch] '" << watcher->GetName()
<< "' watches index " << index << " -> "
<< ((watched != NULL) ? watched->GetName() : "(unbound)")
<< endl << flush;
}
}
}
//
//-----------------------------------------------------------------------
// THE MYOMER CHAIN (binary ctor sweep, part_012.c:15871: the mech+0x7ac
+38
View File
@@ -519,3 +519,41 @@ The fix needs the streamed watch index out of the watcher resource plus
the ctor bind, in the shape the crit-table binding already uses. That is
a proper brick, not a guess, and guessing a binding is exactly what this
project's rules forbid -- so it is recorded here for the next sitting.
## 5.3.132 -- THE WATCHERS ARE BOUND (the family stops being inert)
The missing piece found in 5.3.131 is landed. `HeatWatcher` has always
streamed `watchedSubsystem` and read it into a member; nothing ever turned
that index into the link `UpdateWatch` resolves. The Mech ctor now binds
them in a POST-WALK pass -- necessarily post-walk, because a watcher may
watch a subsystem with a HIGHER roster id, which does not exist yet while
the segment walk is still running -- with out-of-range and self-reference
skipped rather than trusted.
THE BINDINGS PROVE THEMSELVES. Every index resolves to a semantically
right target on bhk1, which a wrong offset could not do:
Gyroscope -> Avionics HUD -> Avionics
Torso -> Myomers Searchlight -> Avionics
AmmoBinAFC100 -> AFC100 AmmoBinLRM15_1 -> LRM15_1
AmmoBinLRM15_2 -> LRM15_2
The gyro and HUD watch the avionics bus, the torso watches the muscles
that move it, and every ammo bin watches its own gun.
### The next question, now sharply posed
With the link live the gyro's watchdog moved 0 -> 1, so it is no longer
the NULL fallback. But 1 is not Ready (4), and `UpdateWatch` can produce
1 two ways: the watched subsystem reporting NoVoltage, or the BROWNOUT
branch (watched Ready, but its generator's measured voltage at or below
`minVoltage * RatedVoltage`).
Avionics is classID 3011 -- a SENSOR instance, named "Avionics" in the art
-- and the roster-live line reports a Sensor at voltState 4. So the
watched subsystem looks READY, which points at the BROWNOUT branch firing
persistently. Next sitting: is `minVoltage` authored/read correctly on
these watchers, or is the reconstructed generator genuinely sitting at the
brownout threshold? Log the watched level and the measured/rated pair
side by side to separate them -- do not adjust a threshold to make an
alarm quiet.