Stop false publish-stale containment
All checks were successful
deploy / deploy (push) Successful in 31s

Proof: Sentinel no longer raises publish-stale before any matching quote exists, preventing false executor auto-disarm during quiet or pre-match periods; regression tests cover both the false case and the real stalled-after-match case.

Assumptions: A publish-path failure is only meaningful after at least one matching quote has been observed for the active pair.

Still fake: The dashboard still lacks deep ingest diagnostics for why quotes are filtered, so pair-filter mismatch analysis is not yet visible at a glance.
This commit is contained in:
philipp 2026-04-08 23:21:51 +02:00
parent 96b5e3cbe7
commit f5ee95b325
3 changed files with 56 additions and 9 deletions

View file

@ -13,6 +13,7 @@ import {
buildRuntimeAlert, buildRuntimeAlert,
createRuntimeHealthThresholds, createRuntimeHealthThresholds,
evaluateRuntimeHealth, evaluateRuntimeHealth,
shouldRaiseIngestPublishStale,
shouldContainExecutorForAlerts, shouldContainExecutorForAlerts,
} from '../core/runtime-health.mjs'; } from '../core/runtime-health.mjs';
import { import {
@ -298,14 +299,13 @@ function buildDeterministicRuntimeAlerts({ servicesByName, now, previousRuntimeE
})); }));
} }
if ( if (shouldRaiseIngestPublishStale({
(publishedAgeMs == null || publishedAgeMs > thresholds.ingestPublishStaleMs) lastMatchingQuoteAt: ingestState.last_matching_quote_at || null,
|| ( lastPublishedAt: ingestState.last_published_at || null,
matchingQuoteAgeMs != null matchingQuoteAgeMs,
&& matchingQuoteAgeMs <= thresholds.ingestQuoteStaleMs publishedAgeMs,
&& (publishedAgeMs == null || publishedAgeMs > thresholds.ingestPublishStaleMs) publishStaleMs: thresholds.ingestPublishStaleMs,
) })) {
) {
alerts.push(buildRuntimeAlert({ alerts.push(buildRuntimeAlert({
alert_code: 'near_intents_publish_stale', alert_code: 'near_intents_publish_stale',
severity: 'critical', severity: 'critical',

View file

@ -294,6 +294,30 @@ export function buildRuntimeAlert({
}; };
} }
export function shouldRaiseIngestPublishStale({
lastMatchingQuoteAt = null,
lastPublishedAt = null,
matchingQuoteAgeMs = null,
publishedAgeMs = null,
publishStaleMs,
} = {}) {
if (!lastMatchingQuoteAt) return false;
if (!lastPublishedAt) return true;
if (publishedAgeMs == null || publishedAgeMs > publishStaleMs) return true;
if (
matchingQuoteAgeMs != null
&& matchingQuoteAgeMs <= publishStaleMs
&& publishedAgeMs > matchingQuoteAgeMs + 5_000
) {
return true;
}
return false;
}
export function shouldContainExecutorForAlerts(alerts = []) { export function shouldContainExecutorForAlerts(alerts = []) {
const containmentAlertCodes = new Set([ const containmentAlertCodes = new Set([
'near_intents_ingest_disconnected', 'near_intents_ingest_disconnected',

View file

@ -1,7 +1,30 @@
import test from 'node:test'; import test from 'node:test';
import assert from 'node:assert/strict'; import assert from 'node:assert/strict';
import { shouldContainExecutorForAlerts } from '../src/core/runtime-health.mjs'; import {
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 ignores quote-stale-only conditions', () => { test('executor containment ignores quote-stale-only conditions', () => {
assert.equal(shouldContainExecutorForAlerts([{ assert.equal(shouldContainExecutorForAlerts([{