instar 1.3.653 → 1.3.654
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 +105 -3
- 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 +6 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/types.d.ts +11 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.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/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,CAq1gBtE;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),
|
|
@@ -17611,7 +17653,67 @@ export async function startServer(options) {
|
|
|
17611
17653
|
},
|
|
17612
17654
|
});
|
|
17613
17655
|
void peerPresencePuller.pullOnce();
|
|
17614
|
-
const
|
|
17656
|
+
const peerPresenceTick = () => {
|
|
17657
|
+
void peerPresencePuller.pullOnce();
|
|
17658
|
+
// mesh-coherence-live-state-honesty (Fix (b)): the periodic, signal-only live-vs-config
|
|
17659
|
+
// mesh coherence recheck. Dev-gated dark (resolveDevAgentGate on the nested ?.enabled).
|
|
17660
|
+
if (resolveDevAgentGate(config.monitoring?.meshCoherenceLiveCheck?.enabled, config)) {
|
|
17661
|
+
// Backoff: after a failure, skip up to min(consecFailures, MAX_BACKOFF_TICKS) ticks
|
|
17662
|
+
// before retrying. A SUCCESSFUL tick resets the counters (auto-recover).
|
|
17663
|
+
const backoffTicks = Math.min(_meshCoherenceConsecFailures, MAX_BACKOFF_TICKS);
|
|
17664
|
+
if (_meshCoherenceConsecFailures > 0 && _meshCoherenceTicksSinceAttempt < backoffTicks) {
|
|
17665
|
+
_meshCoherenceTicksSinceAttempt += 1;
|
|
17666
|
+
}
|
|
17667
|
+
else {
|
|
17668
|
+
_meshCoherenceTicksSinceAttempt = 0;
|
|
17669
|
+
// Resolve the tuning knobs (both are actually READ): warmupGraceMs overrides the
|
|
17670
|
+
// b.2 grace; emitCap (if set) hard-caps re-emits per code per process.
|
|
17671
|
+
const warmupGraceMs = config.monitoring?.meshCoherenceLiveCheck?.warmupGraceMs ?? MESH_WARMUP_GRACE_MS;
|
|
17672
|
+
const emitCap = config.monitoring?.meshCoherenceLiveCheck?.emitCap; // undefined ⇒ unbounded
|
|
17673
|
+
const recorder = getFeatureMetricsRecorder();
|
|
17674
|
+
// THROW-SAFETY (Decision #11): the live registry read can throw on a corrupt /
|
|
17675
|
+
// mid-write registry. A signal-only check must NEVER crash the tick. On any read
|
|
17676
|
+
// failure emit a TRANSITION-GATED 'error' metric row, advance the backoff, and
|
|
17677
|
+
// do NOT touch the transition state (fail toward silence).
|
|
17678
|
+
try {
|
|
17679
|
+
const live = {
|
|
17680
|
+
boundHost: meshResolvedBindHost,
|
|
17681
|
+
selfEndpoints: getSelfMeshEndpoints?.() ?? [],
|
|
17682
|
+
uptimeMs: process.uptime() * 1000,
|
|
17683
|
+
};
|
|
17684
|
+
const warnings = checkMeshLiveStateCoherence(config.multiMachine, true, live, warmupGraceMs);
|
|
17685
|
+
const nowCodes = new Set(warnings.map((w) => w.code));
|
|
17686
|
+
let firedThisTick = false;
|
|
17687
|
+
for (const w of warnings) {
|
|
17688
|
+
if (!_meshCoherenceLastCodes.has(w.code)) { // TRANSITION-ONLY (absent→present)
|
|
17689
|
+
const count = _meshCoherenceEmitCounts.get(w.code) ?? 0;
|
|
17690
|
+
if (emitCap === undefined || count < emitCap) { // emitCap is READ here
|
|
17691
|
+
console.log(pc.yellow(` ⚠ mesh-live-coherence [${w.code}]: ${w.message}`));
|
|
17692
|
+
_meshCoherenceEmitCounts.set(w.code, count + 1);
|
|
17693
|
+
firedThisTick = true;
|
|
17694
|
+
}
|
|
17695
|
+
}
|
|
17696
|
+
}
|
|
17697
|
+
recorder?.record({ feature: 'mesh-coherence-live', kind: 'event', outcome: firedThisTick ? 'fired' : 'noop' });
|
|
17698
|
+
_meshCoherenceLastCodes = nowCodes; // LEVEL-TRIGGERED reset
|
|
17699
|
+
_meshCoherenceConsecFailures = 0; // SUCCESS resets the backoff
|
|
17700
|
+
_meshCoherenceFailing = false; // clear the latch
|
|
17701
|
+
}
|
|
17702
|
+
catch {
|
|
17703
|
+
// @silent-fallback-ok: signal-only honesty observer; a registry read error must
|
|
17704
|
+
// never crash the tick. TRANSITION-GATED observability — emit ONE 'error' row on
|
|
17705
|
+
// the healthy→failing transition (not every attempt), leave the divergence
|
|
17706
|
+
// transition state untouched (fail toward silence), and advance the backoff.
|
|
17707
|
+
if (!_meshCoherenceFailing) {
|
|
17708
|
+
recorder?.record({ feature: 'mesh-coherence-live', kind: 'event', outcome: 'error' });
|
|
17709
|
+
_meshCoherenceFailing = true;
|
|
17710
|
+
}
|
|
17711
|
+
_meshCoherenceConsecFailures += 1;
|
|
17712
|
+
}
|
|
17713
|
+
}
|
|
17714
|
+
}
|
|
17715
|
+
};
|
|
17716
|
+
const peerPresenceTimer = setInterval(peerPresenceTick, 30_000);
|
|
17615
17717
|
if (typeof peerPresenceTimer.unref === 'function')
|
|
17616
17718
|
peerPresenceTimer.unref();
|
|
17617
17719
|
const { resolveSessionPoolStage: _resolveSessionPoolStage } = await import('../core/inboundQueueConfig.js');
|