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