fix(agent): network link changes no longer count as enrollment activity

network_state_change and network_connectivity_check join the non-activity
list next to power_state_change. A flapping dock or access point kept the
idle-stopped periodic collectors running for the whole episode and reset
the stall clock of the enrollment it was stalling. The events are emitted
unchanged; the device-info network snapshots stay activity.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Oliver Kieselbach
2026-09-22 00:48:50 +02:00
parent d6d9638981
commit f252a0709f
2 changed files with 27 additions and 0 deletions
@@ -37,6 +37,12 @@ namespace AutopilotMonitor.Agent.V2.Core.Tests.Orchestration
[InlineData("modern_deployment_log")]
// Environment observation — battery drain on an idle device must not reset idle clocks.
[InlineData("power_state_change")]
// A flapping link is environment too: it must neither keep the collectors awake nor
// reset the stall clock of the enrollment it is stalling.
[InlineData("network_state_change")]
[InlineData("network_connectivity_check")]
// Bookkeeping of health-script runs that were deliberately not reported.
[InlineData("script_recurrence_summary")]
// Agent health / control / transport — not device/enrollment progress (P2).
[InlineData("collector_degraded")]
[InlineData("telemetry_upload_poisoned")]
@@ -67,6 +73,18 @@ namespace AutopilotMonitor.Agent.V2.Core.Tests.Orchestration
Assert.True(SignalActivityClassifier.IsRealActivity(DecisionSignalKind.InformationalEvent, payload));
}
[Theory]
// Only the link-change pair is exempt. The device-info snapshots are emitted at start
// and at the end, not per flap, and stay activity.
[InlineData("network_interface_info")]
[InlineData("wifi_signal_info")]
[InlineData("network_bandwidth_estimate")]
public void Other_network_events_remain_activity(string eventType)
{
var payload = new Dictionary<string, string> { [SignalPayloadKeys.EventType] = eventType };
Assert.True(SignalActivityClassifier.IsRealActivity(DecisionSignalKind.InformationalEvent, payload));
}
[Theory]
// Genuine ModernDeployment warnings/errors stay real activity — only the Info/Debug
// `modern_deployment_log` forwarding is excluded.
@@ -61,6 +61,15 @@ namespace AutopilotMonitor.Agent.V2.Core.Orchestration
// detection — the exact scenario the power watcher exists to observe.
SharedConstants.EventTypes.PowerStateChange,
// Same for the network link: a dock or access point that flaps for hours (field:
// 288 lost/connected pairs in 11 h, each with its connectivity check) is not
// enrollment progress. Counted as activity it kept the periodic collectors running
// for the whole episode and hid the stall it was causing, because every flap reset
// the stall clock. Progress that follows a reconnect arrives as its own download,
// app or phase event.
SharedConstants.EventTypes.NetworkStateChange,
SharedConstants.EventTypes.NetworkConnectivityCheck,
// Same reasoning for the system timeline watcher: a clock step, a wake from standby,
// or a backfilled episode at agent start is environment observation and must not
// reset the idle/stall clocks.