instar 1.3.400 → 1.3.402

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.
Files changed (37) hide show
  1. package/dashboard/index.html +48 -18
  2. package/dist/commands/server.d.ts.map +1 -1
  3. package/dist/commands/server.js +59 -1
  4. package/dist/commands/server.js.map +1 -1
  5. package/dist/core/EnrollmentWizard.d.ts +84 -0
  6. package/dist/core/EnrollmentWizard.d.ts.map +1 -0
  7. package/dist/core/EnrollmentWizard.js +107 -0
  8. package/dist/core/EnrollmentWizard.js.map +1 -0
  9. package/dist/core/FrameworkLoginDriver.d.ts +85 -0
  10. package/dist/core/FrameworkLoginDriver.d.ts.map +1 -0
  11. package/dist/core/FrameworkLoginDriver.js +110 -0
  12. package/dist/core/FrameworkLoginDriver.js.map +1 -0
  13. package/dist/core/PendingLoginStore.d.ts +118 -0
  14. package/dist/core/PendingLoginStore.d.ts.map +1 -0
  15. package/dist/core/PendingLoginStore.js +201 -0
  16. package/dist/core/PendingLoginStore.js.map +1 -0
  17. package/dist/core/types.d.ts +8 -0
  18. package/dist/core/types.d.ts.map +1 -1
  19. package/dist/core/types.js.map +1 -1
  20. package/dist/scaffold/templates.d.ts.map +1 -1
  21. package/dist/scaffold/templates.js +1 -0
  22. package/dist/scaffold/templates.js.map +1 -1
  23. package/dist/server/AgentServer.d.ts +1 -0
  24. package/dist/server/AgentServer.d.ts.map +1 -1
  25. package/dist/server/AgentServer.js +1 -0
  26. package/dist/server/AgentServer.js.map +1 -1
  27. package/dist/server/routes.d.ts +2 -0
  28. package/dist/server/routes.d.ts.map +1 -1
  29. package/dist/server/routes.js +59 -0
  30. package/dist/server/routes.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/data/builtin-manifest.json +47 -47
  33. package/src/scaffold/templates.ts +1 -0
  34. package/upgrades/1.3.401.md +30 -0
  35. package/upgrades/1.3.402.md +64 -0
  36. package/upgrades/side-effects/dashboard-stream-phase3-ui.md +58 -0
  37. package/upgrades/side-effects/subscription-auth-enrollment.md +91 -0
@@ -212,9 +212,11 @@
212
212
  background: #3a2a1b;
213
213
  color: #fbbf24;
214
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; }
215
+ /* A session running on ANOTHER machine — now clickable; selecting it
216
+ streams its terminal here via the cross-machine relay (§2.2). The badge
217
+ already names the machine, so a slightly dimmed row is enough hint. */
218
+ .session-item.remote { opacity: 0.9; cursor: pointer; }
219
+ .session-item.remote:hover { opacity: 1; }
218
220
 
219
221
  .type-badge {
220
222
  padding: 1px 6px;
@@ -3582,6 +3584,7 @@
3582
3584
  let remoteSessions = [];
3583
3585
  let selfMachineNickname = null;
3584
3586
  let activeSession = null;
3587
+ let activeMachineId = null; // non-null when the active session streams from a peer (§2.2)
3585
3588
  let term = null;
3586
3589
  let fitAddon = null;
3587
3590
  let historyLinesLoaded = 2000; // matches initial subscribe capture
@@ -3677,6 +3680,12 @@
3677
3680
  ws.onopen = () => {
3678
3681
  reconnectAttempts = 0;
3679
3682
  updateConnectionStatus(true);
3683
+ // Resubscribe the active session after a (re)connect so a server
3684
+ // restart doesn't strand the terminal (§2.5). Remote sessions carry
3685
+ // their machineId so the resubscribe re-opens the relay.
3686
+ if (activeSession) {
3687
+ wsSend({ type: 'subscribe', session: activeSession, ...(activeMachineId ? { machineId: activeMachineId } : {}) });
3688
+ }
3680
3689
  };
3681
3690
 
3682
3691
  ws.onclose = () => {
@@ -3768,7 +3777,21 @@
3768
3777
  break;
3769
3778
 
3770
3779
  case 'error':
3771
- console.error('[ws]', msg.message);
3780
+ // Pool Dashboard Streaming (§2.4): every remote-stream failure state
3781
+ // is shown honestly in the terminal — never a frozen/black screen or
3782
+ // a silent swallow. Only surface errors for the session in view.
3783
+ if (msg.code && term && (msg.session === activeSession || !msg.session)) {
3784
+ const m = {
3785
+ 'machine-unreachable': '\r\n\x1b[31m--- That machine is unreachable. ---\x1b[0m\r\n',
3786
+ 'peer-stream-lost': '\r\n\x1b[33m--- Stream lost — reconnecting… ---\x1b[0m\r\n',
3787
+ 'input-not-allowed': '\r\n\x1b[33m[remote typing is disabled on this machine — turn it on in that machine\'s settings]\x1b[0m\r\n',
3788
+ 'session-transferred': `\r\n\x1b[33m--- This session moved to ${msg.newMachineId || 'another machine'} — reselect it to follow. ---\x1b[0m\r\n`,
3789
+ 'invalid-session': '\r\n\x1b[31m--- Invalid session name. ---\x1b[0m\r\n',
3790
+ 'session-not-found': '\r\n\x1b[31m--- Session not found on that machine. ---\x1b[0m\r\n',
3791
+ }[msg.code];
3792
+ if (m) { term.write(m); break; }
3793
+ }
3794
+ console.error('[ws]', msg.code || msg.message);
3772
3795
  break;
3773
3796
  }
3774
3797
  }
@@ -3845,13 +3868,12 @@
3845
3868
  el = document.createElement('div');
3846
3869
  el.className = 'session-item';
3847
3870
  el.dataset.session = sessionRowKey(session);
3848
- if (session.remote) {
3849
- // A remote session's terminal streams on ITS machine's dashboard
3850
- // clicking here can't subscribe to it, so the row is informational.
3851
- el.title = `Running on ${session.machineNickname || session.machineId || 'another machine'} — open that machine's dashboard to interact.`;
3852
- } else {
3853
- el.onclick = () => selectSession(session.tmuxSession, session);
3854
- }
3871
+ // Pool Dashboard Streaming (§2.2): remote sessions are now clickable —
3872
+ // selecting one streams it from its owning machine via the relay.
3873
+ el.title = session.remote
3874
+ ? `Running on ${session.machineNickname || session.machineId || 'another machine'} — click to stream it here.`
3875
+ : '';
3876
+ el.onclick = () => selectSession(session.tmuxSession, session);
3855
3877
  list.appendChild(el);
3856
3878
  }
3857
3879
 
@@ -3912,11 +3934,13 @@
3912
3934
 
3913
3935
  // ── Terminal ──────────────────────────────────────────────
3914
3936
  function selectSession(tmuxSession, session) {
3915
- // Unsubscribe from previous
3937
+ // Unsubscribe from previous (carry its machineId so a remote unsub routes).
3916
3938
  if (activeSession) {
3917
- wsSend({ type: 'unsubscribe', session: activeSession });
3939
+ wsSend({ type: 'unsubscribe', session: activeSession, ...(activeMachineId ? { machineId: activeMachineId } : {}) });
3918
3940
  }
3919
3941
 
3942
+ // Pool Dashboard Streaming (§2.2): a remote session streams from its owner.
3943
+ activeMachineId = session.remote ? (session.machineId || null) : null;
3920
3944
  activeSession = tmuxSession;
3921
3945
  userIsFollowing = true; // Reset scroll tracking on session switch
3922
3946
  hideResumeButton(); // Carry-over button from prior session would be misleading
@@ -3958,9 +3982,12 @@
3958
3982
  initTerminal();
3959
3983
  }
3960
3984
 
3961
- // Clear and subscribe
3985
+ // Clear and subscribe (remote → carry machineId so the server relays).
3962
3986
  term.clear();
3963
- wsSend({ type: 'subscribe', session: tmuxSession });
3987
+ if (activeMachineId) {
3988
+ term.write(`\x1b[2m[streaming from ${session.machineNickname || activeMachineId}…]\x1b[0m\r\n`);
3989
+ }
3990
+ wsSend({ type: 'subscribe', session: tmuxSession, ...(activeMachineId ? { machineId: activeMachineId } : {}) });
3964
3991
 
3965
3992
  // Update active state in sidebar
3966
3993
  renderSessionList();
@@ -4203,25 +4230,28 @@
4203
4230
  }
4204
4231
 
4205
4232
  // ── Input ────────────────────────────────────────────────
4233
+ // Remote sessions carry machineId so the server relays input to the owner
4234
+ // (which enforces its own allowRemoteInput gate; a refusal returns an
4235
+ // input-not-allowed error frame, surfaced in the terminal — never silent).
4206
4236
  function sendInput() {
4207
4237
  const input = document.getElementById('termInput');
4208
4238
  const text = input.value;
4209
4239
  if (!text || !activeSession) return;
4210
4240
 
4211
- wsSend({ type: 'input', session: activeSession, text });
4241
+ wsSend({ type: 'input', session: activeSession, text, ...(activeMachineId ? { machineId: activeMachineId } : {}) });
4212
4242
  input.value = '';
4213
4243
  input.focus();
4214
4244
  }
4215
4245
 
4216
4246
  function sendKey(key) {
4217
4247
  if (!activeSession) return;
4218
- wsSend({ type: 'key', session: activeSession, key });
4248
+ wsSend({ type: 'key', session: activeSession, key, ...(activeMachineId ? { machineId: activeMachineId } : {}) });
4219
4249
  }
4220
4250
 
4221
4251
  function sendSpecial(text) {
4222
4252
  if (!activeSession) return;
4223
4253
  // Send literal text without Enter
4224
- wsSend({ type: 'key', session: activeSession, key: text });
4254
+ wsSend({ type: 'key', session: activeSession, key: text, ...(activeMachineId ? { machineId: activeMachineId } : {}) });
4225
4255
  }
4226
4256
 
4227
4257
  // ── New Session Modal ────────────────────────────────────
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQ3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAuBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAiG7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AA6JtD,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA05BD,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,GAC/F,IAAI,CAyUN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAk9TtE;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;AAaH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQ3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAuBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAiG7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AA6JtD,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA05BD,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,GAC/F,IAAI,CAyUN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA0gUtE;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"}
@@ -6494,6 +6494,64 @@ export async function startServer(options) {
6494
6494
  quotaPoller.start();
6495
6495
  console.log(pc.green(' Subscription quota poller started'));
6496
6496
  }
6497
+ // EnrollmentWizard — mobile-first new-account login (P2.1 of the Subscription
6498
+ // & Auth Standard). Dark with the pool: the /subscription-pool/enroll routes
6499
+ // do nothing until an operator starts an enrollment. The login driver reuses
6500
+ // the proven tmux-spawn + capture-pane primitive (the same one /login uses) to
6501
+ // scrape the PUBLIC verification URL / device code — NEVER a token. The new
6502
+ // account's CLAUDE_CONFIG_DIR isolates the login to its own slot, so enrolling
6503
+ // a 2nd account never clobbers the 1st.
6504
+ const { PendingLoginStore } = await import('../core/PendingLoginStore.js');
6505
+ const { EnrollmentWizard } = await import('../core/EnrollmentWizard.js');
6506
+ const { FrameworkLoginDriver } = await import('../core/FrameworkLoginDriver.js');
6507
+ const DEFAULT_ENROLL_LOGIN_COMMANDS = {
6508
+ 'claude-code': 'claude auth login',
6509
+ 'codex-cli': 'codex login',
6510
+ 'gemini-cli': 'gemini',
6511
+ 'pi-cli': 'pi login',
6512
+ };
6513
+ const enrollLoginCommands = {
6514
+ ...DEFAULT_ENROLL_LOGIN_COMMANDS,
6515
+ ...(config.subscriptionPool?.enrollment?.loginCommands ?? {}),
6516
+ };
6517
+ const pendingLoginStore = new PendingLoginStore({ stateDir: config.stateDir });
6518
+ const enrollmentWizard = new EnrollmentWizard({
6519
+ store: pendingLoginStore,
6520
+ logger: { log: (m) => console.log(m), warn: (m) => console.warn(m) },
6521
+ driveLogin: new FrameworkLoginDriver({
6522
+ capture: async (session) => sessionManager.captureOutput(session, 120) || '',
6523
+ spawn: async ({ framework, configHome }) => {
6524
+ const tmuxPath = detectTmuxPath();
6525
+ if (!tmuxPath)
6526
+ throw new Error('tmux not available for enrollment login');
6527
+ const baseCmd = enrollLoginCommands[framework] ?? `${framework} login`;
6528
+ // env-prefix sets the per-account config home for the login process so
6529
+ // the credential lands in its own slot (CLAUDE_CONFIG_DIR isolation).
6530
+ const cmd = configHome
6531
+ ? `env CLAUDE_CONFIG_DIR=${JSON.stringify(configHome)} ${baseCmd}`
6532
+ : baseCmd;
6533
+ const slug = (configHome ?? framework).replace(/[^a-zA-Z0-9]+/g, '-').slice(-24);
6534
+ const session = `instar-enroll-${framework}-${slug}`;
6535
+ try {
6536
+ execFileSync(tmuxPath, ['kill-session', '-t', `=${session}`], { stdio: 'ignore' });
6537
+ }
6538
+ catch { /* @silent-fallback-ok: no prior enroll session for this slot */ }
6539
+ execFileSync(tmuxPath, ['new-session', '-d', '-s', session, cmd], { timeout: 10000 });
6540
+ return { session };
6541
+ },
6542
+ logger: { log: (m) => console.log(m), warn: (m) => console.warn(m) },
6543
+ }).asLoginDriver(),
6544
+ });
6545
+ // Background auto-reissue sweep — refreshes an expired login code without the
6546
+ // operator asking (the pi-live-test gap). Inert with no pending logins; the
6547
+ // timer is unref'd so it never holds the process open.
6548
+ const enrollReissueTimer = setInterval(() => {
6549
+ enrollmentWizard
6550
+ .reissueExpired()
6551
+ .catch(() => { });
6552
+ }, config.subscriptionPool?.enrollment?.reissueSweepMs ?? 5 * 60_000);
6553
+ if (enrollReissueTimer.unref)
6554
+ enrollReissueTimer.unref();
6497
6555
  // Commitment Sentinel — LLM-powered scanner that finds unregistered commitments.
6498
6556
  let commitmentSentinel;
6499
6557
  if (sharedIntelligence) {
@@ -11282,7 +11340,7 @@ export async function startServer(options) {
11282
11340
  catch (err) {
11283
11341
  console.log(pc.dim(` [session-pool] rollout gate not wired: ${err instanceof Error ? err.message : String(err)}`));
11284
11342
  }
11285
- 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, subscriptionPool, quotaPoller, quotaAwareScheduler: _quotaAwareScheduler ?? undefined, 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, a2aDeliveryTracker: a2aDeliveryTracker ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, meshRpcDispatcher, workingSetPullCoordinator, commitmentReplicaStore, forwardCommitmentMutate, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, streamTicketStore: _streamTicketStore ?? undefined, poolStreamAllowRemoteInput: config.dashboard?.poolStream?.allowRemoteInput ?? false, poolStreamConnector: _poolStreamConnector ?? 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 });
11343
+ 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, subscriptionPool, quotaPoller, quotaAwareScheduler: _quotaAwareScheduler ?? undefined, enrollmentWizard, 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, a2aDeliveryTracker: a2aDeliveryTracker ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, meshRpcDispatcher, workingSetPullCoordinator, commitmentReplicaStore, forwardCommitmentMutate, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, streamTicketStore: _streamTicketStore ?? undefined, poolStreamAllowRemoteInput: config.dashboard?.poolStream?.allowRemoteInput ?? false, poolStreamConnector: _poolStreamConnector ?? 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 });
11286
11344
  // Resolve the late-bound topic-operator getter (increment 2e): routing was
11287
11345
  // wired before the server existed; from here on inbound binds use the
11288
11346
  // server's own store instance.