Skip to content

Commit 9a1bded

Browse files
authored
Merge pull request #24 from dfeen87/copilot/harden-and-fix-wnn-telemetry
Harden DSM WNN telemetry enforcement and close rollback edge-case faults
2 parents c07ba21 + 88a3f05 commit 9a1bded

3 files changed

Lines changed: 70 additions & 4 deletions

File tree

include/raps/safety/deterministic_safety_monitor.hpp

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ constexpr double MIN_RESONANCE_AMPLITUDE_CUTOFF = 0.10;
3131
// WNN Constraints
3232
constexpr double WNN_MAX_CURVATURE_PROXY = 5.0e-11;
3333
constexpr double WNN_MIN_OSCILLATORY_PREFACTOR = 0.85;
34+
constexpr double INVALID_TELEMETRY_SENTINEL = -1.0;
3435

3536
} // namespace DSM_Config
3637

@@ -80,6 +81,8 @@ class DeterministicSafetyMonitor {
8081
bool safing_sequence_active_;
8182

8283
bool hasInvalidInputs(const DsmSensorInputs& inputs) const;
84+
bool hasInvalidWnnTelemetry(const WnnTelemetry& wnn_telem) const;
85+
bool isWnnThresholdBreached(const WnnTelemetry& wnn_telem) const;
8386
bool checkResonanceStability(double A_t, double J_coupling) const;
8487
double estimateCurvatureScalar(double dilation) const;
8588
bool checkCurvatureViolation(double R_estimated) const;
@@ -120,6 +123,22 @@ DeterministicSafetyMonitor::hasInvalidInputs(
120123
!std::isfinite(inputs.current_resonance_amplitude);
121124
}
122125

126+
inline bool
127+
DeterministicSafetyMonitor::hasInvalidWnnTelemetry(
128+
const WnnTelemetry& wnn_telem
129+
) const {
130+
return !std::isfinite(wnn_telem.curvature_proxy) ||
131+
!std::isfinite(wnn_telem.oscillatory_prefactor);
132+
}
133+
134+
inline bool
135+
DeterministicSafetyMonitor::isWnnThresholdBreached(
136+
const WnnTelemetry& wnn_telem
137+
) const {
138+
return wnn_telem.curvature_proxy > DSM_Config::WNN_MAX_CURVATURE_PROXY ||
139+
wnn_telem.oscillatory_prefactor < DSM_Config::WNN_MIN_OSCILLATORY_PREFACTOR;
140+
}
141+
123142
inline bool
124143
DeterministicSafetyMonitor::checkResonanceStability(
125144
double A_t,
@@ -193,11 +212,27 @@ DeterministicSafetyMonitor::pollWnnAndEnforce(
193212
uint32_t rollback_count,
194213
PhysicsState& active_state_pointer
195214
) {
196-
if (wnn_telem.curvature_proxy > DSM_Config::WNN_MAX_CURVATURE_PROXY ||
197-
wnn_telem.oscillatory_prefactor < DSM_Config::WNN_MIN_OSCILLATORY_PREFACTOR) {
215+
const bool invalid_wnn_input = hasInvalidWnnTelemetry(wnn_telem);
216+
const bool threshold_breach = isWnnThresholdBreached(wnn_telem);
217+
218+
if (invalid_wnn_input || threshold_breach) {
219+
// Keep safing active until the broader control loop restores margins.
220+
safing_sequence_active_ = true;
221+
if (invalid_wnn_input) {
222+
std::cerr << "DSM ALERT: Non-finite WNN telemetry detected — ROLLBACK\n";
223+
} else {
224+
std::cerr << "DSM ALERT: WNN thresholds exceeded — ROLLBACK\n";
225+
}
226+
227+
const double logged_curvature = std::isfinite(wnn_telem.curvature_proxy)
228+
? wnn_telem.curvature_proxy
229+
: DSM_Config::INVALID_TELEMETRY_SENTINEL;
230+
const double logged_prefactor = std::isfinite(wnn_telem.oscillatory_prefactor)
231+
? wnn_telem.oscillatory_prefactor
232+
: DSM_Config::INVALID_TELEMETRY_SENTINEL;
198233

199234
// Breach detected! Log to ITL and execute immediate rollback
200-
itl_manager.log_wnn_rollback_event(wnn_telem.curvature_proxy, wnn_telem.oscillatory_prefactor);
235+
itl_manager.log_wnn_rollback_event(logged_curvature, logged_prefactor);
201236

202237
return trigger_wnn_immediate_rollback(
203238
rollback_store,

src/raps/rollback_execution.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ inline bool trigger_wnn_immediate_rollback(
5353
uint32_t rollback_count,
5454
PhysicsState& active_state_pointer
5555
) {
56-
if (rollback_count == 0) {
56+
if (rollback_count == 0 || rollback_store == nullptr) {
5757
return false;
5858
}
5959

tests/sil/test_rollback_execution.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,36 @@ void test_rollback_validation() {
7676
expect_true(tx_id.length() > 0, "tx_id is generated");
7777
}
7878

79+
void test_wnn_rollback_hardening() {
80+
std::cout << "--- Testing WNN Rollback Hardening ---\n";
81+
82+
PhysicsState active_state{};
83+
active_state.timestamp_ms = 10;
84+
85+
// 1. Null rollback store with non-zero count must fail safely
86+
bool null_store_result = trigger_wnn_immediate_rollback(
87+
nullptr,
88+
1,
89+
active_state
90+
);
91+
expect_false(
92+
null_store_result,
93+
"trigger_wnn_immediate_rollback fails safely for null rollback store"
94+
);
95+
96+
// 2. Empty rollback store must fail safely
97+
RollbackPlan store[1]{};
98+
bool empty_store_result = trigger_wnn_immediate_rollback(
99+
store,
100+
0,
101+
active_state
102+
);
103+
expect_false(
104+
empty_store_result,
105+
"trigger_wnn_immediate_rollback fails safely for empty rollback store"
106+
);
107+
}
108+
79109
int main() {
80110
std::cout << "========================================================\n";
81111
std::cout << " SIL TEST: Rollback Execution Logic\n";
@@ -85,6 +115,7 @@ int main() {
85115
PlatformHAL::seed_rng_for_stubs(12345);
86116

87117
test_rollback_validation();
118+
test_wnn_rollback_hardening();
88119

89120
std::cout << "--------------------------------------------------------\n";
90121
if (g_failures == 0) {

0 commit comments

Comments
 (0)