import test from 'node:test'; import assert from 'node:assert/strict'; import { buildExecutorRuntimeAlerts, buildMakerCompetitivenessRuntimeAlerts, deriveServiceHealth, shouldContainExecutorForAlerts, shouldRaiseIngestPublishStale, } from '../src/core/runtime-health.mjs'; test('publish stale does not raise before any matching quote exists', () => { assert.equal(shouldRaiseIngestPublishStale({ lastMatchingQuoteAt: null, lastPublishedAt: null, matchingQuoteAgeMs: null, publishedAgeMs: null, publishStaleMs: 30_000, }), false); }); test('publish stale raises after a matching quote exists but no publish follows', () => { assert.equal(shouldRaiseIngestPublishStale({ lastMatchingQuoteAt: '2026-04-08T20:45:00.000Z', lastPublishedAt: null, matchingQuoteAgeMs: 10_000, publishedAgeMs: null, publishStaleMs: 30_000, }), true); }); test('executor containment stays disabled for quote-stale-only conditions', () => { assert.equal(shouldContainExecutorForAlerts([{ alert_code: 'near_intents_quotes_stale', severity: 'critical', }]), false); }); test('executor containment stays disabled even for broken truth path alerts', () => { assert.equal(shouldContainExecutorForAlerts([{ alert_code: 'near_intents_ingest_disconnected', severity: 'critical', }]), false); assert.equal(shouldContainExecutorForAlerts([{ alert_code: 'near_intents_publish_stale', severity: 'critical', }]), false); assert.equal(shouldContainExecutorForAlerts([{ alert_code: 'history_writer_stalled', severity: 'critical', }]), false); }); test('armed service treats critical truth alerts for any active pair as critical', () => { const health = deriveServiceHealth({ service: 'strategy-engine', snapshot: { reachable: true, state: { armed: true, }, health: { ok: true, }, }, activePairs: [ 'btc->eure', 'btc->usdc', ], activeAlerts: [{ alert_code: 'reference_price_stale', severity: 'critical', service_scope: 'strategy-engine', pair: 'btc->usdc', }], now: '2026-05-18T10:00:00.000Z', }); assert.equal(health.status, 'critical'); assert.equal(health.label, 'armed on stale truth'); }); test('maker competitiveness alerts are pair-scoped for high quote-finished relay failure rate', () => { const alerts = buildMakerCompetitivenessRuntimeAlerts({ makerCompetitiveness: { generated_at: '2026-05-18T10:00:00.000Z', groups: [ { pair: 'nbtc->usdc', direction: 'base_to_quote', request_kind: 'exact_in', result_code: 'submission_failed', failure_category: 'quote_not_found_or_finished', quote_age_bucket: '100-250ms', notional_bucket: '5-10', count: 4, }, { pair: 'nbtc->usdc', direction: 'base_to_quote', request_kind: 'exact_in', result_code: 'quote_response_ok', failure_category: null, quote_age_bucket: '<100ms', notional_bucket: '5-10', count: 1, accepted_count: 1, }, { pair: 'nbtc->eure', result_code: 'quote_response_ok', failure_category: null, count: 8, accepted_count: 8, }, ], }, }); assert.equal(alerts.length, 1); assert.equal(alerts[0].alert_code, 'maker_quote_not_found_or_finished_rate_high'); assert.equal(alerts[0].service_scope, 'strategy-engine'); assert.equal(alerts[0].pair, 'nbtc->usdc'); assert.equal(alerts[0].details.quote_not_found_or_finished_count, 4); assert.equal(alerts[0].details.quote_not_found_or_finished_rate, 0.8); }); test('history writer retention pressure and stale rollups surface as runtime warnings', () => { const pressure = deriveServiceHealth({ service: 'history-writer', snapshot: { reachable: true, state: { database_connectivity: true, last_write_at: '2026-06-06T10:59:59.000Z', retention_mode: 'pressure', }, health: { ok: true }, }, now: '2026-06-06T11:00:00.000Z', }); assert.equal(pressure.status, 'warning'); assert.equal(pressure.label, 'storage pressure'); const stale = deriveServiceHealth({ service: 'history-writer', snapshot: { reachable: true, state: { database_connectivity: true, last_write_at: '2026-06-06T10:59:59.000Z', retention_mode: 'blocked_rollup_stale', }, health: { ok: true }, }, now: '2026-06-06T11:00:00.000Z', }); assert.equal(stale.status, 'warning'); assert.equal(stale.label, 'rollup stale'); assert.ok(stale.reasons.some((reason) => /fail-closed/.test(reason))); }); test('trade executor salt and queue state surface as runtime health warnings', () => { const health = deriveServiceHealth({ service: 'trade-executor', snapshot: { reachable: true, state: { armed: true, verifier_salt_cache: { configured: true, has_cached_salt: false, salt_fresh: false, }, executor_queue_delay: { status: 'warning', warning_reason: 'recent command_to_executor_ms max 1500ms exceeds 1000ms', }, }, health: { ok: true }, }, now: '2026-06-12T10:00:00.000Z', }); assert.equal(health.status, 'warning'); assert.ok(health.reasons.includes('verifier salt cache is stale or unavailable')); assert.ok(health.reasons.includes('recent command_to_executor_ms max 1500ms exceeds 1000ms')); }); test('executor runtime alerts cover stale salt, refresh failure, and queue delay', () => { const alerts = buildExecutorRuntimeAlerts({ executor: { reachable: true, state: { verifier_salt_cache: { configured: true, has_cached_salt: true, salt_fresh: false, salt_age_ms: 750, max_age_ms: 500, refresh_in_flight: false, last_refresh_started_at: '2026-06-12T09:59:59.000Z', last_refresh_completed_at: '2026-06-12T09:59:59.100Z', last_refresh_duration_ms: 100, last_refresh_error: { name: 'Error', message: 'rpc unavailable', }, }, executor_queue_delay: { status: 'critical', latest_ms: 200, max_ms: 7_500, p90_ms: 5_200, p99_ms: 7_500, sample_count: 10, latest_command_id: 'cmd-1', latest_quote_id: 'quote-1', }, }, }, thresholds: { executorQueueDelayWarningMs: 1_000, executorQueueDelayCriticalMs: 5_000, }, pair: 'nbtc->eure', }); assert.deepEqual( alerts.map((alert) => alert.alert_code), [ 'trade_executor_verifier_salt_unavailable', 'trade_executor_verifier_salt_refresh_failed', 'trade_executor_command_queue_delay_high', ], ); assert.equal(alerts[0].severity, 'warning'); assert.equal(alerts[1].details.last_refresh_error.message, 'rpc unavailable'); assert.equal(alerts[2].severity, 'critical'); assert.equal(alerts[2].details.p90_ms, 5_200); });