instar 1.3.270 → 1.3.271
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/dashboard/index.html +73 -11
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +15 -2
- package/dist/commands/server.js.map +1 -1
- package/dist/coordination/ReviewExchange.d.ts +135 -0
- package/dist/coordination/ReviewExchange.d.ts.map +1 -0
- package/dist/coordination/ReviewExchange.js +192 -0
- package/dist/coordination/ReviewExchange.js.map +1 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +33 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/SecretStore.d.ts.map +1 -1
- package/dist/core/SecretStore.js +10 -1
- package/dist/core/SecretStore.js.map +1 -1
- package/dist/core/TransferByNickname.d.ts +6 -0
- package/dist/core/TransferByNickname.d.ts.map +1 -1
- package/dist/core/TransferByNickname.js +18 -6
- package/dist/core/TransferByNickname.js.map +1 -1
- package/dist/core/seamlessnessConfig.d.ts.map +1 -1
- package/dist/core/seamlessnessConfig.js +12 -1
- package/dist/core/seamlessnessConfig.js.map +1 -1
- package/dist/core/types.d.ts +23 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +8 -1
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/scheduler/MentorAutonomousGuardian.d.ts.map +1 -1
- package/dist/scheduler/MentorAutonomousGuardian.js +1 -0
- package/dist/scheduler/MentorAutonomousGuardian.js.map +1 -1
- package/dist/server/AgentServer.d.ts +5 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +9 -1
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +16 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts +8 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +227 -4
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +64 -64
- package/src/scaffold/templates.ts +8 -1
- package/upgrades/1.3.271.md +154 -0
- package/upgrades/autoloop-gate-compliance.eli16.md +11 -0
- package/upgrades/side-effects/autoloop-gate-compliance.md +43 -0
- package/upgrades/side-effects/dashboard-pool-sessions.md +103 -0
- package/upgrades/side-effects/review-exchange-protocol.md +60 -0
- package/upgrades/side-effects/secret-drop-store-first.md +117 -0
- package/upgrades/side-effects/transfer-idempotency-exactly-once.md +105 -0
package/dashboard/index.html
CHANGED
|
@@ -203,6 +203,19 @@
|
|
|
203
203
|
.model-badge.sonnet { background: #1b2e4e; color: #60a5fa; }
|
|
204
204
|
.model-badge.haiku { background: #1b3e3e; color: #5eead4; }
|
|
205
205
|
|
|
206
|
+
/* Which machine a session runs on (multi-machine pool). */
|
|
207
|
+
.machine-badge {
|
|
208
|
+
padding: 1px 6px;
|
|
209
|
+
border-radius: 4px;
|
|
210
|
+
font-size: 10px;
|
|
211
|
+
font-weight: 600;
|
|
212
|
+
background: #3a2a1b;
|
|
213
|
+
color: #fbbf24;
|
|
214
|
+
}
|
|
215
|
+
/* A session running on ANOTHER machine — visible, but its terminal can't
|
|
216
|
+
stream here (open that machine's dashboard to interact). */
|
|
217
|
+
.session-item.remote { opacity: 0.8; cursor: default; }
|
|
218
|
+
|
|
206
219
|
.type-badge {
|
|
207
220
|
padding: 1px 6px;
|
|
208
221
|
border-radius: 4px;
|
|
@@ -3472,6 +3485,11 @@
|
|
|
3472
3485
|
let ws = null;
|
|
3473
3486
|
let token = '';
|
|
3474
3487
|
let sessions = [];
|
|
3488
|
+
// Sessions running on OTHER machines in the pool (GET /sessions?scope=pool).
|
|
3489
|
+
// Kept separate from `sessions` because the WebSocket replaces that array
|
|
3490
|
+
// with LOCAL sessions on every broadcast — merging would be wiped each tick.
|
|
3491
|
+
let remoteSessions = [];
|
|
3492
|
+
let selfMachineNickname = null;
|
|
3475
3493
|
let activeSession = null;
|
|
3476
3494
|
let term = null;
|
|
3477
3495
|
let fitAddon = null;
|
|
@@ -3518,6 +3536,7 @@
|
|
|
3518
3536
|
connectWebSocket();
|
|
3519
3537
|
startWaPolling();
|
|
3520
3538
|
startVitalSigns();
|
|
3539
|
+
startPoolSessionsPolling();
|
|
3521
3540
|
} else {
|
|
3522
3541
|
showAuthError('Incorrect PIN');
|
|
3523
3542
|
}
|
|
@@ -3543,6 +3562,7 @@
|
|
|
3543
3562
|
connectWebSocket();
|
|
3544
3563
|
startWaPolling();
|
|
3545
3564
|
startVitalSigns();
|
|
3565
|
+
startPoolSessionsPolling();
|
|
3546
3566
|
}
|
|
3547
3567
|
})
|
|
3548
3568
|
.catch(() => {});
|
|
@@ -3681,17 +3701,31 @@
|
|
|
3681
3701
|
}
|
|
3682
3702
|
|
|
3683
3703
|
// ── Session List ─────────────────────────────────────────
|
|
3704
|
+
// Stable per-row key. Remote sessions are namespaced by machine so a tmux
|
|
3705
|
+
// name reused on two machines never collides with a local row.
|
|
3706
|
+
function sessionRowKey(s) {
|
|
3707
|
+
return s.remote ? `remote:${s.machineId || '?'}:${s.tmuxSession}` : s.tmuxSession;
|
|
3708
|
+
}
|
|
3709
|
+
|
|
3684
3710
|
function renderSessionList() {
|
|
3685
3711
|
const list = document.getElementById('sessionList');
|
|
3686
3712
|
const empty = document.getElementById('emptyState');
|
|
3687
3713
|
const count = document.getElementById('sessionCount');
|
|
3688
3714
|
|
|
3689
|
-
|
|
3715
|
+
// Local sessions (live via WebSocket) + every other machine's sessions
|
|
3716
|
+
// (via the /sessions?scope=pool poll). Local rows inherit this machine's
|
|
3717
|
+
// nickname so EVERY row states where it runs once the pool is live.
|
|
3718
|
+
const all = [
|
|
3719
|
+
...sessions.map(s => (s.machineNickname || !selfMachineNickname) ? s : { ...s, machineNickname: selfMachineNickname }),
|
|
3720
|
+
...remoteSessions,
|
|
3721
|
+
];
|
|
3722
|
+
|
|
3723
|
+
count.textContent = all.length;
|
|
3690
3724
|
// Keep tab bar count in sync
|
|
3691
3725
|
const tabCount = document.getElementById('tabSessionCount');
|
|
3692
|
-
if (tabCount) tabCount.textContent =
|
|
3726
|
+
if (tabCount) tabCount.textContent = all.length;
|
|
3693
3727
|
|
|
3694
|
-
if (
|
|
3728
|
+
if (all.length === 0) {
|
|
3695
3729
|
empty.style.display = 'flex';
|
|
3696
3730
|
// Clear any existing session items
|
|
3697
3731
|
list.querySelectorAll('.session-item').forEach(el => el.remove());
|
|
@@ -3708,29 +3742,35 @@
|
|
|
3708
3742
|
|
|
3709
3743
|
// Remove sessions no longer running
|
|
3710
3744
|
for (const [name, el] of existing) {
|
|
3711
|
-
if (!
|
|
3745
|
+
if (!all.find(s => sessionRowKey(s) === name)) {
|
|
3712
3746
|
el.remove();
|
|
3713
3747
|
}
|
|
3714
3748
|
}
|
|
3715
3749
|
|
|
3716
3750
|
// Add/update sessions
|
|
3717
|
-
for (const session of
|
|
3718
|
-
let el = existing.get(session
|
|
3751
|
+
for (const session of all) {
|
|
3752
|
+
let el = existing.get(sessionRowKey(session));
|
|
3719
3753
|
if (!el) {
|
|
3720
3754
|
el = document.createElement('div');
|
|
3721
3755
|
el.className = 'session-item';
|
|
3722
|
-
el.dataset.session = session
|
|
3723
|
-
|
|
3756
|
+
el.dataset.session = sessionRowKey(session);
|
|
3757
|
+
if (session.remote) {
|
|
3758
|
+
// A remote session's terminal streams on ITS machine's dashboard —
|
|
3759
|
+
// clicking here can't subscribe to it, so the row is informational.
|
|
3760
|
+
el.title = `Running on ${session.machineNickname || session.machineId || 'another machine'} — open that machine's dashboard to interact.`;
|
|
3761
|
+
} else {
|
|
3762
|
+
el.onclick = () => selectSession(session.tmuxSession, session);
|
|
3763
|
+
}
|
|
3724
3764
|
list.appendChild(el);
|
|
3725
3765
|
}
|
|
3726
3766
|
|
|
3727
3767
|
const elapsed = formatElapsed(session.startedAt);
|
|
3728
3768
|
const model = session.model || 'opus';
|
|
3729
|
-
const isActive = session.tmuxSession === activeSession;
|
|
3769
|
+
const isActive = !session.remote && session.tmuxSession === activeSession;
|
|
3730
3770
|
const sType = session.type || (session.jobSlug ? 'job' : 'interactive');
|
|
3731
3771
|
const tele = session.telemetry;
|
|
3732
3772
|
|
|
3733
|
-
el.className = `session-item${isActive ? ' active' : ''}`;
|
|
3773
|
+
el.className = `session-item${isActive ? ' active' : ''}${session.remote ? ' remote' : ''}`;
|
|
3734
3774
|
|
|
3735
3775
|
let telemetryHtml = '';
|
|
3736
3776
|
if (tele) {
|
|
@@ -3765,12 +3805,13 @@
|
|
|
3765
3805
|
el.innerHTML = `
|
|
3766
3806
|
<div class="session-name-row">
|
|
3767
3807
|
<div class="session-name">${escapeHtml(session.platformName || session.name)}</div>
|
|
3768
|
-
|
|
3808
|
+
${session.remote ? '' : `<button class="session-close-btn" data-tmux="${escapeHtml(session.tmuxSession)}" data-name="${escapeHtml(session.name)}" onclick="event.stopPropagation();closeSession(this.dataset.tmux,this.dataset.name)" title="Close session">×</button>`}
|
|
3769
3809
|
</div>
|
|
3770
3810
|
<div class="session-meta">
|
|
3771
3811
|
<span class="type-badge ${sType}">${sType}</span>
|
|
3772
3812
|
<span class="model-badge ${model}">${model}</span>
|
|
3773
3813
|
<span class="platform-badge ${platform}" title="${platformLabel}">${platformIcon}</span>
|
|
3814
|
+
${session.machineNickname ? `<span class="machine-badge" title="Machine this session runs on">${escapeHtml(session.machineNickname)}</span>` : ''}
|
|
3774
3815
|
<span>${elapsed}</span>
|
|
3775
3816
|
</div>
|
|
3776
3817
|
${telemetryHtml}
|
|
@@ -4210,6 +4251,27 @@
|
|
|
4210
4251
|
const WA_QR_TIMEOUT_MS = 30000; // 30s timeout for QR appearance
|
|
4211
4252
|
let waLastError = ''; // last error message for display
|
|
4212
4253
|
|
|
4254
|
+
// ── Pool-wide sessions (multi-machine) ───────────────────
|
|
4255
|
+
// The WebSocket only carries THIS machine's sessions. When the agent runs a
|
|
4256
|
+
// multi-machine pool, poll the aggregated view so every session — on every
|
|
4257
|
+
// machine — shows in the list, each tagged with the machine it runs on.
|
|
4258
|
+
let poolPollTimer = null;
|
|
4259
|
+
function startPoolSessionsPolling() {
|
|
4260
|
+
if (poolPollTimer) return;
|
|
4261
|
+
const poll = async () => {
|
|
4262
|
+
try {
|
|
4263
|
+
const r = await fetch('/sessions?scope=pool', { headers: { 'Authorization': `Bearer ${token}` } });
|
|
4264
|
+
if (!r.ok) return;
|
|
4265
|
+
const j = await r.json();
|
|
4266
|
+
selfMachineNickname = (j.pool && j.pool.selfMachineNickname) || null;
|
|
4267
|
+
remoteSessions = (j.sessions || []).filter(s => s.remote === true);
|
|
4268
|
+
renderSessionList();
|
|
4269
|
+
} catch { /* best-effort — peers may be offline; next tick retries */ }
|
|
4270
|
+
};
|
|
4271
|
+
poll();
|
|
4272
|
+
poolPollTimer = setInterval(poll, 15000);
|
|
4273
|
+
}
|
|
4274
|
+
|
|
4213
4275
|
function startWaPolling() {
|
|
4214
4276
|
if (waQrInterval) return;
|
|
4215
4277
|
waQrPollingStarted = Date.now();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA4SH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA4SH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAqxDD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAi/QtE;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
|
@@ -326,6 +326,9 @@ let _meshSelfId = null;
|
|
|
326
326
|
* a moved topic's prior history from the router (bug #2). Set in the mesh block where
|
|
327
327
|
* the peer-URL resolver + coordinator are in scope. */
|
|
328
328
|
let _resolveRouterUrl = null;
|
|
329
|
+
/** Every OTHER active machine with a known URL — backs GET /sessions?scope=pool
|
|
330
|
+
* (pool-wide session aggregation for the dashboard). Set in the same mesh block. */
|
|
331
|
+
let _resolvePeerUrls = null;
|
|
329
332
|
/** Multi-Machine Session Pool §L4: per-topic placement pin store ("move this to <nickname>"). */
|
|
330
333
|
let _topicPinStore = null;
|
|
331
334
|
/** Cross-machine secret-sync (spec Phase 4): route-facing handle (push lever + read-only status). */
|
|
@@ -9295,6 +9298,10 @@ export async function startServer(options) {
|
|
|
9295
9298
|
const h = coordinator.getSyncStatus().leaseHolder;
|
|
9296
9299
|
return h && h !== meshSelfId ? peerUrl(h) : null;
|
|
9297
9300
|
};
|
|
9301
|
+
_resolvePeerUrls = () => meshIdMgr
|
|
9302
|
+
.getActiveMachines()
|
|
9303
|
+
.filter((m) => m.machineId !== meshSelfId && !!m.entry.lastKnownUrl)
|
|
9304
|
+
.map((m) => ({ machineId: m.machineId, url: m.entry.lastKnownUrl }));
|
|
9298
9305
|
// ── Self-nickname convergence (§L4, 2026-06-04 live-caught fix) ──
|
|
9299
9306
|
// `updateNickname` (PATCH /pool/machines) is local-only, so a rename applied on a
|
|
9300
9307
|
// PEER's registry never reaches the owning machine — leaving that machine unable to
|
|
@@ -9602,6 +9609,10 @@ export async function startServer(options) {
|
|
|
9602
9609
|
isOnline: (m) => machinePoolRegistry?.getCapacity(m)?.online ?? false,
|
|
9603
9610
|
currentOwnerOf: (sk) => ownReg.ownerOf(sk),
|
|
9604
9611
|
isMidReply: () => false, // best-effort; the pin takes effect on the next routed message
|
|
9612
|
+
// Pin-aware idempotency: a duplicate "move to X" while already pinned
|
|
9613
|
+
// to X (e.g. a lifeline retry / post-restart replay of the same
|
|
9614
|
+
// message) no-ops as "already there" instead of burning the rate limit.
|
|
9615
|
+
currentPinOf: (sk) => _topicPinStore?.get(sk)?.preferredMachine ?? null,
|
|
9605
9616
|
lastPlacementUpdateAt: (sk) => _topicPinStore?.lastUpdatedAtMs(sk) ?? null,
|
|
9606
9617
|
now: () => Date.now(),
|
|
9607
9618
|
}, sessionKey);
|
|
@@ -9616,7 +9627,9 @@ export async function startServer(options) {
|
|
|
9616
9627
|
}
|
|
9617
9628
|
catch { /* best-effort; route() re-places regardless once the owner is cleared */ }
|
|
9618
9629
|
await telegram?.sendToTopic(topicId, plan.action === 'noop'
|
|
9619
|
-
?
|
|
9630
|
+
? (plan.detail === 'already-on-target'
|
|
9631
|
+
? `This conversation is already running on ${cmd.nickname} — nothing to move.`
|
|
9632
|
+
: `This conversation is already pinned to ${cmd.nickname} — it'll keep running there.`)
|
|
9620
9633
|
: `Moving this conversation to ${cmd.nickname} — it'll pick up there on your next message.`).catch(() => { });
|
|
9621
9634
|
console.log(pc.green(` [session-pool] topic ${topicId} pinned to ${target} (${plan.action}) via "${cmd.matchedVerb}"`));
|
|
9622
9635
|
return { handled: true };
|
|
@@ -9708,7 +9721,7 @@ export async function startServer(options) {
|
|
|
9708
9721
|
catch (err) {
|
|
9709
9722
|
console.log(pc.dim(` [session-pool] rollout gate not wired: ${err instanceof Error ? err.message : String(err)}`));
|
|
9710
9723
|
}
|
|
9711
|
-
const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, semanticMemory, activitySentinel, rateLimitSentinel, releaseReadinessSentinel: releaseReadinessSentinel ?? undefined, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, sessionRefresh: _sessionRefresh ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, leaseTransport, onLeasePullRequest: () => leaseCoordinatorRef?.currentLease() ?? null, liveTailReceiver, handoffWireTransport, onHandoffBegin, onHandoffInitiate: handoffInitiate, handoffInProgress: handoffSentinelInProgress, messageLedger, currentInboundByTopic, replyMarkerTransport, onReplyMarker: messageLedger ? (marker) => { const m = marker; messageLedger.applyRemoteReplyMarker(m.dedupeKey, { platform: m.platform, replyIdempotencyKey: m.replyIdempotencyKey, epoch: m.epoch, topic: m.topic ?? null }); } : undefined, whatsapp: whatsappAdapter, slack: slackAdapter, imessage: imessageAdapter, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, conversationStore, warrantsReplyGate, collaborationSurfacer, threadResumeMap, topicLinkageHandler: topicLinkageHandler ?? undefined, threadlineRelayClient, threadlineReplyWaiters, listenerManager: listenerManager ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, meshRpcDispatcher, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, secretSync: _secretSyncHandle ?? undefined, meshSelfId: _meshSelfId ?? undefined, resolveRouterUrl: _resolveRouterUrl ?? undefined, sessionPoolE2EResultStore, proxyCoordinator, topicIntentStore, topicIntentArcCheck, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, briefDeps, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper, agentWorktreeReaper, mcpProcessReaper, geminiLoopRunner, sleepController, agentActivityState, reapLog, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier });
|
|
9724
|
+
const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, semanticMemory, activitySentinel, rateLimitSentinel, releaseReadinessSentinel: releaseReadinessSentinel ?? undefined, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, sessionRefresh: _sessionRefresh ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, leaseTransport, onLeasePullRequest: () => leaseCoordinatorRef?.currentLease() ?? null, liveTailReceiver, handoffWireTransport, onHandoffBegin, onHandoffInitiate: handoffInitiate, handoffInProgress: handoffSentinelInProgress, messageLedger, currentInboundByTopic, replyMarkerTransport, onReplyMarker: messageLedger ? (marker) => { const m = marker; messageLedger.applyRemoteReplyMarker(m.dedupeKey, { platform: m.platform, replyIdempotencyKey: m.replyIdempotencyKey, epoch: m.epoch, topic: m.topic ?? null }); } : undefined, whatsapp: whatsappAdapter, slack: slackAdapter, imessage: imessageAdapter, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, conversationStore, warrantsReplyGate, collaborationSurfacer, threadResumeMap, topicLinkageHandler: topicLinkageHandler ?? undefined, threadlineRelayClient, threadlineReplyWaiters, listenerManager: listenerManager ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, meshRpcDispatcher, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, secretSync: _secretSyncHandle ?? undefined, meshSelfId: _meshSelfId ?? undefined, resolveRouterUrl: _resolveRouterUrl ?? undefined, resolvePeerUrls: _resolvePeerUrls ?? undefined, sessionPoolE2EResultStore, proxyCoordinator, topicIntentStore, topicIntentArcCheck, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, briefDeps, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper, agentWorktreeReaper, mcpProcessReaper, geminiLoopRunner, sleepController, agentActivityState, reapLog, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier });
|
|
9712
9725
|
// Boot-recovery (tunnel-failure-resilience spec Part 6): if the agent
|
|
9713
9726
|
// died mid-relay-episode, the persisted tunnel.json carries
|
|
9714
9727
|
// rotationPending=true. Rotate the dashboard PIN + authToken BEFORE
|