instar 1.3.653 → 1.3.655
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +124 -4
- package/dist/commands/server.js.map +1 -1
- package/dist/core/configCoherence.d.ts +46 -5
- package/dist/core/configCoherence.d.ts.map +1 -1
- package/dist/core/configCoherence.js +101 -12
- package/dist/core/configCoherence.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +12 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/types.d.ts +24 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/PresenceProxy.d.ts +14 -0
- package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
- package/dist/monitoring/PresenceProxy.js +103 -11
- package/dist/monitoring/PresenceProxy.js.map +1 -1
- package/dist/monitoring/ResumeQueue.d.ts +17 -2
- package/dist/monitoring/ResumeQueue.d.ts.map +1 -1
- package/dist/monitoring/ResumeQueue.js +19 -2
- package/dist/monitoring/ResumeQueue.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.3.654.md +26 -0
- package/upgrades/1.3.655.md +29 -0
- package/upgrades/side-effects/honest-session-state-surfaces.md +185 -0
- package/upgrades/side-effects/mesh-coherence-live-state-honesty.md +53 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2CH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAU3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAwBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAwH7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AA+EtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AAyID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAy4CD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GACpD,IAAI,CA8eN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2CH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAU3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAwBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAwH7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AA+EtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AAyID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAy4CD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GACpD,IAAI,CA8eN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA02gBtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
|
package/dist/commands/server.js
CHANGED
|
@@ -49,6 +49,7 @@ import { BootHealthBeacon } from '../server/BootHealthBeacon.js';
|
|
|
49
49
|
import { TelegramAdapter, TOPIC_STYLE, selectTopicEmoji } from '../messaging/TelegramAdapter.js';
|
|
50
50
|
import { getTelegramInboundDir } from '../messaging/shared/telegramInboundFiles.js';
|
|
51
51
|
import { RelationshipManager } from '../core/RelationshipManager.js';
|
|
52
|
+
import { getFeatureMetricsRecorder } from '../core/CircuitBreakingIntelligenceProvider.js';
|
|
52
53
|
import { configureLlmCircuitBreaker, llmCircuitAvailable } from '../core/LlmCircuitBreaker.js';
|
|
53
54
|
import { computeSelfQuotaState } from '../core/selfQuotaState.js';
|
|
54
55
|
import { isClaudeForbidden } from '../core/claudeForbiddenGuard.js';
|
|
@@ -93,7 +94,7 @@ import { MultiMachineCoordinator } from '../core/MultiMachineCoordinator.js';
|
|
|
93
94
|
import { isRemotelyHandled } from '../core/SessionRouter.js';
|
|
94
95
|
import { isSlackSessionKey, reconstructSlackMessage } from '../core/SlackForwardBridge.js';
|
|
95
96
|
import { formatForwardedTopicContext } from '../core/ForwardedTopicContext.js';
|
|
96
|
-
import { resolveAdvertisedMeshUrl, advertiseSelfMeshUrl, detectTailscaleIp, pickPrimaryLanIp, computeSelfMeshEndpoints, advertiseSelfMeshEndpoints } from '../core/MeshUrlAdvertiser.js';
|
|
97
|
+
import { resolveAdvertisedMeshUrl, advertiseSelfMeshUrl, detectTailscaleIp, pickPrimaryLanIp, computeSelfMeshEndpoints, advertiseSelfMeshEndpoints, resolveMeshBindHost } from '../core/MeshUrlAdvertiser.js';
|
|
97
98
|
import { PeerEndpointResolver } from '../core/PeerEndpointResolver.js';
|
|
98
99
|
import { relayOutbound } from '../core/TelegramRelay.js';
|
|
99
100
|
import { GitSyncManager } from '../core/GitSync.js';
|
|
@@ -111,7 +112,7 @@ import { LocalLeaseStore } from '../core/LocalLeaseStore.js';
|
|
|
111
112
|
import { LeaseCoordinator } from '../core/LeaseCoordinator.js';
|
|
112
113
|
import { isPeerPresumedDead } from '../core/leaseLiveness.js';
|
|
113
114
|
import { readPollActive, pidAlive as pollPidAlive } from '../core/pollIntent.js';
|
|
114
|
-
import { checkMultiMachineConfigCoherence } from '../core/configCoherence.js';
|
|
115
|
+
import { checkMultiMachineConfigCoherence, checkMeshLiveStateCoherence, MESH_WARMUP_GRACE_MS } from '../core/configCoherence.js';
|
|
115
116
|
import { HttpLeaseTransport } from '../core/HttpLeaseTransport.js';
|
|
116
117
|
import { PeerEndpointRecorder } from '../core/PeerEndpointRecorder.js';
|
|
117
118
|
import { HttpLiveTailTransport } from '../core/HttpLiveTailTransport.js';
|
|
@@ -3881,6 +3882,33 @@ export async function startServer(options) {
|
|
|
3881
3882
|
// construction (far below) can wire the /api/lease[/pull] receivers to real registry fns.
|
|
3882
3883
|
let peerEndpointRecorder;
|
|
3883
3884
|
let getSelfMeshEndpoints;
|
|
3885
|
+
// mesh-coherence-live-state-honesty (Fix (b) / Decision #5): the resolved server bind host,
|
|
3886
|
+
// a BOOT CONSTANT. Declared `let` at OUTER scope (the same scope as getSelfMeshEndpoints)
|
|
3887
|
+
// and assigned inside the mesh-init block so the peerPresenceTimer closure (far below) can
|
|
3888
|
+
// reach it — a const inside the block would be UNREACHABLE from the timer.
|
|
3889
|
+
let meshResolvedBindHost;
|
|
3890
|
+
// mesh-coherence-live-state-honesty (Fix (b) / Decision #6): transition-only emit state +
|
|
3891
|
+
// capped-backoff failure state for the periodic live-coherence check, at outer scope so the
|
|
3892
|
+
// peerPresenceTimer closure persists them across ticks.
|
|
3893
|
+
// _meshCoherenceLastCodes: the SET of codes emitted on the previous tick — a code logs
|
|
3894
|
+
// ONLY on absent→present; a LEVEL-TRIGGERED reset clears a code when its divergence
|
|
3895
|
+
// resolves, so a later recurrence logs fresh (one line per divergence episode).
|
|
3896
|
+
// _meshCoherenceEmitCounts: per-code re-emit tally enforcing the optional emitCap ceiling.
|
|
3897
|
+
// _meshCoherenceConsecFailures/_meshCoherenceTicksSinceAttempt: capped consecutive-failure
|
|
3898
|
+
// backoff so a sustained-corrupt registry does not re-throw-and-swallow every 30s.
|
|
3899
|
+
// _meshCoherenceFailing: a healthy→failing LATCH so the 'error' metric is TRANSITION-GATED
|
|
3900
|
+
// (one row when the read STARTS failing, not one per attempt).
|
|
3901
|
+
let _meshCoherenceLastCodes = new Set();
|
|
3902
|
+
const _meshCoherenceEmitCounts = new Map();
|
|
3903
|
+
let _meshCoherenceConsecFailures = 0;
|
|
3904
|
+
let _meshCoherenceTicksSinceAttempt = 0;
|
|
3905
|
+
let _meshCoherenceFailing = false;
|
|
3906
|
+
// Half-open breaker (all three brakes): BACKOFF (a read failure trips it to ≤1 attempt per
|
|
3907
|
+
// MAX_BACKOFF_TICKS×30s ≈ 10min), BREAKER (the failing-latch + backoff; a successful read
|
|
3908
|
+
// CLOSES it), CAP (MAX_BACKOFF_TICKS floors the re-probe rate; the 'error' metric is
|
|
3909
|
+
// transition-gated). Deliberately HALF-OPEN (re-probing), NOT hard-STOP: a signal-only
|
|
3910
|
+
// honesty observer that STOPS attempting goes BLIND if the registry recovers.
|
|
3911
|
+
const MAX_BACKOFF_TICKS = 20;
|
|
3884
3912
|
let leaseCoordinatorRef;
|
|
3885
3913
|
let liveTailBuffer;
|
|
3886
3914
|
let liveTailSendTransport;
|
|
@@ -4040,6 +4068,20 @@ export async function startServer(options) {
|
|
|
4040
4068
|
// and the LIVE meshTransport gate. Shared by the receiver routes (sender/puller
|
|
4041
4069
|
// direction) and the transport's pull-RESPONSE path (holder direction).
|
|
4042
4070
|
getSelfMeshEndpoints = () => idMgr.getMachineEndpoints(selfMachineId);
|
|
4071
|
+
// mesh-coherence-live-state-honesty (Fix (b) / Decision #5): assign the resolved bind
|
|
4072
|
+
// host from the SAME meshBindActive expression the AgentServer bind callsite uses
|
|
4073
|
+
// (server.ts construction → AgentServer.ts:3469). boundHost is a BOOT CONSTANT (the bind
|
|
4074
|
+
// cannot change without a restart — which is exactly the b.1 divergence), so a single
|
|
4075
|
+
// boot-scope assignment is the live truth.
|
|
4076
|
+
{
|
|
4077
|
+
const meshBindActiveForCoherence = coordinator.managers.identityManager.hasIdentity() &&
|
|
4078
|
+
config.multiMachine?.meshTransport?.enabled !== false;
|
|
4079
|
+
meshResolvedBindHost = resolveMeshBindHost({
|
|
4080
|
+
configHost: config.host,
|
|
4081
|
+
meshBindActive: meshBindActiveForCoherence,
|
|
4082
|
+
meshBindHostOverride: config.multiMachine?.meshTransport?.bindHost,
|
|
4083
|
+
});
|
|
4084
|
+
}
|
|
4043
4085
|
peerEndpointRecorder = new PeerEndpointRecorder({
|
|
4044
4086
|
getPeerEndpoints: (id) => idMgr.getMachineEndpoints(id),
|
|
4045
4087
|
updateMachineEndpoints: (id, eps) => idMgr.updateMachineEndpoints(id, eps),
|
|
@@ -6630,7 +6672,14 @@ export async function startServer(options) {
|
|
|
6630
6672
|
}
|
|
6631
6673
|
// Wired by the resume-queue boot block (Part B) once the queue exists;
|
|
6632
6674
|
// stays false (no "restart queued" lines) until then or in dry-run.
|
|
6675
|
+
// OWNERSHIP predicate (paused-BLIND) — read by the PromiseBeacon I2
|
|
6676
|
+
// double-spawn coordination guard (must keep deferring to the queue while
|
|
6677
|
+
// paused). Distinct from resumeClaimableForSession below.
|
|
6633
6678
|
let resumeQueuedForSession = () => false;
|
|
6679
|
+
// CLAIMABILITY predicate (paused-AWARE) — read by the ReapNotifier
|
|
6680
|
+
// "restart is queued" copy (honest-session-state-surfaces Finding (c)): a
|
|
6681
|
+
// paused queue won't revive yet, so the claim is suppressed while paused.
|
|
6682
|
+
let resumeClaimableForSession = () => false;
|
|
6634
6683
|
const reapNotifier = new ReapNotifier({
|
|
6635
6684
|
resolveTopic: (tmuxSession) => {
|
|
6636
6685
|
const t = telegram?.getTopicForSession(tmuxSession);
|
|
@@ -6655,7 +6704,9 @@ export async function startServer(options) {
|
|
|
6655
6704
|
recordNotify: (e) => reapLog.recordNotify(e),
|
|
6656
6705
|
quietHoursEndAt: (now) => notificationBatcher.quietHoursEndAt(now),
|
|
6657
6706
|
summaryReleaseAt: (now) => notificationBatcher.nextSummaryReleaseAt(now),
|
|
6658
|
-
|
|
6707
|
+
// Finding (c): the user-facing "restart is queued" copy reads the
|
|
6708
|
+
// CLAIMABILITY predicate (false while paused), NOT the ownership one.
|
|
6709
|
+
resumeQueuedFor: (tmuxSession) => resumeClaimableForSession(tmuxSession),
|
|
6659
6710
|
// Honest-recycle (honest-session-recycle-spec): tell ReapNotifier whether
|
|
6660
6711
|
// this session's topic has an ACTIVE autonomous run (and how long is left),
|
|
6661
6712
|
// so an age-limit RECYCLE of a still-active run reads as a continuation
|
|
@@ -6919,7 +6970,10 @@ export async function startServer(options) {
|
|
|
6919
6970
|
else {
|
|
6920
6971
|
// Feed the notifier's "restart is queued" line (live, non-dry-run only).
|
|
6921
6972
|
const rq = resumeQueue;
|
|
6973
|
+
// OWNERSHIP (paused-blind) → I2 double-spawn guard at :11980.
|
|
6922
6974
|
resumeQueuedForSession = (tmuxSession) => rq.hasLiveQueuedEntryFor(tmuxSession);
|
|
6975
|
+
// CLAIMABILITY (paused-aware) → ReapNotifier "restart is queued" copy.
|
|
6976
|
+
resumeClaimableForSession = (tmuxSession) => rq.hasClaimableQueuedEntryFor(tmuxSession);
|
|
6923
6977
|
const resolveTopicForTmux = (tmuxSession) => {
|
|
6924
6978
|
try {
|
|
6925
6979
|
const t = telegram?.getTopicForSession(tmuxSession);
|
|
@@ -10719,6 +10773,12 @@ export async function startServer(options) {
|
|
|
10719
10773
|
// honest classifier must stay silent so the user hears one voice.
|
|
10720
10774
|
// Reuses the same composed checker the SessionReaper uses for its veto.
|
|
10721
10775
|
isStuckRecoveryActive: (sessionName) => wedgeRecoveryActive?.(sessionName) ?? false,
|
|
10776
|
+
// honest-session-state-surfaces Finding (b): lift the Tier-3 honest
|
|
10777
|
+
// stuck classification into Tier 1 / Tier 2. Dev-gated dark — live on
|
|
10778
|
+
// a development agent, dark on the fleet (the flag is OMITTED from
|
|
10779
|
+
// ConfigDefaults so it resolves through the dev-agent gate). Signal
|
|
10780
|
+
// only — changes the standby MESSAGE TEXT, never the schedule/recovery.
|
|
10781
|
+
standbyHonestyTiers: resolveDevAgentGate(config.monitoring?.standbyHonestyTiers?.enabled, config),
|
|
10722
10782
|
// Shared LLM queue (interactive lane) — cross-monitor concurrency
|
|
10723
10783
|
// and daily-spend-cap with PromiseBeacon.
|
|
10724
10784
|
sharedLlmQueue,
|
|
@@ -17611,7 +17671,67 @@ export async function startServer(options) {
|
|
|
17611
17671
|
},
|
|
17612
17672
|
});
|
|
17613
17673
|
void peerPresencePuller.pullOnce();
|
|
17614
|
-
const
|
|
17674
|
+
const peerPresenceTick = () => {
|
|
17675
|
+
void peerPresencePuller.pullOnce();
|
|
17676
|
+
// mesh-coherence-live-state-honesty (Fix (b)): the periodic, signal-only live-vs-config
|
|
17677
|
+
// mesh coherence recheck. Dev-gated dark (resolveDevAgentGate on the nested ?.enabled).
|
|
17678
|
+
if (resolveDevAgentGate(config.monitoring?.meshCoherenceLiveCheck?.enabled, config)) {
|
|
17679
|
+
// Backoff: after a failure, skip up to min(consecFailures, MAX_BACKOFF_TICKS) ticks
|
|
17680
|
+
// before retrying. A SUCCESSFUL tick resets the counters (auto-recover).
|
|
17681
|
+
const backoffTicks = Math.min(_meshCoherenceConsecFailures, MAX_BACKOFF_TICKS);
|
|
17682
|
+
if (_meshCoherenceConsecFailures > 0 && _meshCoherenceTicksSinceAttempt < backoffTicks) {
|
|
17683
|
+
_meshCoherenceTicksSinceAttempt += 1;
|
|
17684
|
+
}
|
|
17685
|
+
else {
|
|
17686
|
+
_meshCoherenceTicksSinceAttempt = 0;
|
|
17687
|
+
// Resolve the tuning knobs (both are actually READ): warmupGraceMs overrides the
|
|
17688
|
+
// b.2 grace; emitCap (if set) hard-caps re-emits per code per process.
|
|
17689
|
+
const warmupGraceMs = config.monitoring?.meshCoherenceLiveCheck?.warmupGraceMs ?? MESH_WARMUP_GRACE_MS;
|
|
17690
|
+
const emitCap = config.monitoring?.meshCoherenceLiveCheck?.emitCap; // undefined ⇒ unbounded
|
|
17691
|
+
const recorder = getFeatureMetricsRecorder();
|
|
17692
|
+
// THROW-SAFETY (Decision #11): the live registry read can throw on a corrupt /
|
|
17693
|
+
// mid-write registry. A signal-only check must NEVER crash the tick. On any read
|
|
17694
|
+
// failure emit a TRANSITION-GATED 'error' metric row, advance the backoff, and
|
|
17695
|
+
// do NOT touch the transition state (fail toward silence).
|
|
17696
|
+
try {
|
|
17697
|
+
const live = {
|
|
17698
|
+
boundHost: meshResolvedBindHost,
|
|
17699
|
+
selfEndpoints: getSelfMeshEndpoints?.() ?? [],
|
|
17700
|
+
uptimeMs: process.uptime() * 1000,
|
|
17701
|
+
};
|
|
17702
|
+
const warnings = checkMeshLiveStateCoherence(config.multiMachine, true, live, warmupGraceMs);
|
|
17703
|
+
const nowCodes = new Set(warnings.map((w) => w.code));
|
|
17704
|
+
let firedThisTick = false;
|
|
17705
|
+
for (const w of warnings) {
|
|
17706
|
+
if (!_meshCoherenceLastCodes.has(w.code)) { // TRANSITION-ONLY (absent→present)
|
|
17707
|
+
const count = _meshCoherenceEmitCounts.get(w.code) ?? 0;
|
|
17708
|
+
if (emitCap === undefined || count < emitCap) { // emitCap is READ here
|
|
17709
|
+
console.log(pc.yellow(` ⚠ mesh-live-coherence [${w.code}]: ${w.message}`));
|
|
17710
|
+
_meshCoherenceEmitCounts.set(w.code, count + 1);
|
|
17711
|
+
firedThisTick = true;
|
|
17712
|
+
}
|
|
17713
|
+
}
|
|
17714
|
+
}
|
|
17715
|
+
recorder?.record({ feature: 'mesh-coherence-live', kind: 'event', outcome: firedThisTick ? 'fired' : 'noop' });
|
|
17716
|
+
_meshCoherenceLastCodes = nowCodes; // LEVEL-TRIGGERED reset
|
|
17717
|
+
_meshCoherenceConsecFailures = 0; // SUCCESS resets the backoff
|
|
17718
|
+
_meshCoherenceFailing = false; // clear the latch
|
|
17719
|
+
}
|
|
17720
|
+
catch {
|
|
17721
|
+
// @silent-fallback-ok: signal-only honesty observer; a registry read error must
|
|
17722
|
+
// never crash the tick. TRANSITION-GATED observability — emit ONE 'error' row on
|
|
17723
|
+
// the healthy→failing transition (not every attempt), leave the divergence
|
|
17724
|
+
// transition state untouched (fail toward silence), and advance the backoff.
|
|
17725
|
+
if (!_meshCoherenceFailing) {
|
|
17726
|
+
recorder?.record({ feature: 'mesh-coherence-live', kind: 'event', outcome: 'error' });
|
|
17727
|
+
_meshCoherenceFailing = true;
|
|
17728
|
+
}
|
|
17729
|
+
_meshCoherenceConsecFailures += 1;
|
|
17730
|
+
}
|
|
17731
|
+
}
|
|
17732
|
+
}
|
|
17733
|
+
};
|
|
17734
|
+
const peerPresenceTimer = setInterval(peerPresenceTick, 30_000);
|
|
17615
17735
|
if (typeof peerPresenceTimer.unref === 'function')
|
|
17616
17736
|
peerPresenceTimer.unref();
|
|
17617
17737
|
const { resolveSessionPoolStage: _resolveSessionPoolStage } = await import('../core/inboundQueueConfig.js');
|