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.
@@ -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,CAgvgBtE;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"}
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"}
@@ -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 peerPresenceTimer = setInterval(() => { void peerPresencePuller.pullOnce(); }, 30_000);
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');