Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions include/raps/safety/deterministic_safety_monitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ constexpr double MIN_RESONANCE_AMPLITUDE_CUTOFF = 0.10;
// WNN Constraints
constexpr double WNN_MAX_CURVATURE_PROXY = 5.0e-11;
constexpr double WNN_MIN_OSCILLATORY_PREFACTOR = 0.85;
constexpr double INVALID_TELEMETRY_SENTINEL = -1.0;

} // namespace DSM_Config

Expand Down Expand Up @@ -80,6 +81,8 @@ class DeterministicSafetyMonitor {
bool safing_sequence_active_;

bool hasInvalidInputs(const DsmSensorInputs& inputs) const;
bool hasInvalidWnnTelemetry(const WnnTelemetry& wnn_telem) const;
bool isWnnThresholdBreached(const WnnTelemetry& wnn_telem) const;
bool checkResonanceStability(double A_t, double J_coupling) const;
double estimateCurvatureScalar(double dilation) const;
bool checkCurvatureViolation(double R_estimated) const;
Expand Down Expand Up @@ -120,6 +123,22 @@ DeterministicSafetyMonitor::hasInvalidInputs(
!std::isfinite(inputs.current_resonance_amplitude);
}

inline bool
DeterministicSafetyMonitor::hasInvalidWnnTelemetry(
const WnnTelemetry& wnn_telem
) const {
return !std::isfinite(wnn_telem.curvature_proxy) ||
!std::isfinite(wnn_telem.oscillatory_prefactor);
}

inline bool
DeterministicSafetyMonitor::isWnnThresholdBreached(
const WnnTelemetry& wnn_telem
) const {
return wnn_telem.curvature_proxy > DSM_Config::WNN_MAX_CURVATURE_PROXY ||
wnn_telem.oscillatory_prefactor < DSM_Config::WNN_MIN_OSCILLATORY_PREFACTOR;
}

inline bool
DeterministicSafetyMonitor::checkResonanceStability(
double A_t,
Expand Down Expand Up @@ -193,11 +212,27 @@ DeterministicSafetyMonitor::pollWnnAndEnforce(
uint32_t rollback_count,
PhysicsState& active_state_pointer
) {
if (wnn_telem.curvature_proxy > DSM_Config::WNN_MAX_CURVATURE_PROXY ||
wnn_telem.oscillatory_prefactor < DSM_Config::WNN_MIN_OSCILLATORY_PREFACTOR) {
const bool invalid_wnn_input = hasInvalidWnnTelemetry(wnn_telem);
const bool threshold_breach = isWnnThresholdBreached(wnn_telem);

if (invalid_wnn_input || threshold_breach) {
// Keep safing active until the broader control loop restores margins.
safing_sequence_active_ = true;
if (invalid_wnn_input) {
std::cerr << "DSM ALERT: Non-finite WNN telemetry detected — ROLLBACK\n";
} else {
std::cerr << "DSM ALERT: WNN thresholds exceeded — ROLLBACK\n";
}

const double logged_curvature = std::isfinite(wnn_telem.curvature_proxy)
? wnn_telem.curvature_proxy
: DSM_Config::INVALID_TELEMETRY_SENTINEL;
const double logged_prefactor = std::isfinite(wnn_telem.oscillatory_prefactor)
? wnn_telem.oscillatory_prefactor
: DSM_Config::INVALID_TELEMETRY_SENTINEL;

// Breach detected! Log to ITL and execute immediate rollback
itl_manager.log_wnn_rollback_event(wnn_telem.curvature_proxy, wnn_telem.oscillatory_prefactor);
itl_manager.log_wnn_rollback_event(logged_curvature, logged_prefactor);

return trigger_wnn_immediate_rollback(
rollback_store,
Expand Down
2 changes: 1 addition & 1 deletion src/raps/rollback_execution.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ inline bool trigger_wnn_immediate_rollback(
uint32_t rollback_count,
PhysicsState& active_state_pointer
) {
if (rollback_count == 0) {
if (rollback_count == 0 || rollback_store == nullptr) {
return false;
}

Expand Down
31 changes: 31 additions & 0 deletions tests/sil/test_rollback_execution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,36 @@ void test_rollback_validation() {
expect_true(tx_id.length() > 0, "tx_id is generated");
}

void test_wnn_rollback_hardening() {
std::cout << "--- Testing WNN Rollback Hardening ---\n";

PhysicsState active_state{};
active_state.timestamp_ms = 10;

// 1. Null rollback store with non-zero count must fail safely
bool null_store_result = trigger_wnn_immediate_rollback(
nullptr,
1,
active_state
);
expect_false(
null_store_result,
"trigger_wnn_immediate_rollback fails safely for null rollback store"
);

// 2. Empty rollback store must fail safely
RollbackPlan store[1]{};
bool empty_store_result = trigger_wnn_immediate_rollback(
store,
0,
active_state
);
expect_false(
empty_store_result,
"trigger_wnn_immediate_rollback fails safely for empty rollback store"
);
}

int main() {
std::cout << "========================================================\n";
std::cout << " SIL TEST: Rollback Execution Logic\n";
Expand All @@ -85,6 +115,7 @@ int main() {
PlatformHAL::seed_rng_for_stubs(12345);

test_rollback_validation();
test_wnn_rollback_hardening();

std::cout << "--------------------------------------------------------\n";
if (g_failures == 0) {
Expand Down
Loading