Merge #591: FOCAS duplicate-sibling tests wait for the first axis pass, not the bootstrap stamp

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-08 01:35:41 -04:00
@@ -53,10 +53,24 @@ public sealed class FocasDuplicateSiblingNameTests
{
var drv = NewDriver(tags);
await drv.InitializeAsync("{}", CancellationToken.None);
var deadline = DateTime.UtcNow + TimeSpan.FromSeconds(5);
while (DateTime.UtcNow < deadline && drv.GetDeviceState(Host)?.LastFixedPollUtc is null)
await Task.Delay(25, TestContext.Current.CancellationToken);
drv.GetDeviceState(Host)!.LastFixedPollUtc.ShouldNotBeNull("the fixed-tree loop never completed a poll");
// LastFixedPollUtc alone is NOT "the first axis pass finished": the bootstrap stamps it
// after the sysinfo probe, before any axis snapshot is published (#591 — under load a
// read slipped into that window and saw BadNodeIdUnknown). Wait for the data itself:
// the last axis slot plus the servo/spindle caches this fake's first tick populates.
var deadline = DateTime.UtcNow + TimeSpan.FromSeconds(30);
var ready = false;
while (!ready && DateTime.UtcNow < deadline)
{
var st = drv.GetDeviceState(Host);
ready = st is not null
&& st.LastFixedPollUtc is not null
&& st.LastFixedSnapshots.ContainsKey(FocasDriver.FixedTreeReference(Host, "Axes/AA_2/AbsolutePosition"))
&& st.LastServoLoads.Count >= 3
&& st.LastSpindleLoads.Count >= 2
&& st.LastSpindleMotorSpeeds.Count >= 2;
if (!ready) await Task.Delay(10, TestContext.Current.CancellationToken);
}
ready.ShouldBeTrue("the fixed-tree loop never completed its first full poll");
return drv;
}