instar 1.3.1649 → 1.3.1651
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/console/accounts.js +2 -1
- package/dashboard/console/agents-model.js +3 -3
- package/dashboard/console/agents.js +7 -4
- package/dashboard/console/console.css +1 -0
- package/dashboard/console/console.js +35 -4
- package/dashboard/console/costs-model.js +12 -0
- package/dashboard/console/costs.js +6 -3
- package/dashboard/console/development-model.js +9 -3
- package/dashboard/console/development.js +7 -4
- package/dashboard/console/home-model.js +30 -14
- package/dashboard/console/mandates.js +3 -3
- package/dashboard/console/needs-model.js +105 -0
- package/dashboard/console/plans.js +2 -1
- package/dashboard/console/secrets.js +2 -2
- package/dashboard/console/ticket-model.js +36 -0
- package/dashboard/console/ui.js +3 -0
- package/dist/cli.js +8 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/install.d.ts +9 -7
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +2 -19
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/machine.d.ts +2 -0
- package/dist/commands/machine.d.ts.map +1 -1
- package/dist/commands/machine.js +19 -0
- package/dist/commands/machine.js.map +1 -1
- package/dist/commands/reflect.d.ts.map +1 -1
- package/dist/commands/reflect.js +2 -0
- package/dist/commands/reflect.js.map +1 -1
- package/dist/commands/route.d.ts.map +1 -1
- package/dist/commands/route.js +2 -0
- package/dist/commands/route.js.map +1 -1
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +537 -21
- package/dist/commands/server.js.map +1 -1
- package/dist/commands/setClaudeKey.d.ts +8 -0
- package/dist/commands/setClaudeKey.d.ts.map +1 -0
- package/dist/commands/setClaudeKey.js +35 -0
- package/dist/commands/setClaudeKey.js.map +1 -0
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +2 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/AccountFollowMeOrchestrator.d.ts.map +1 -1
- package/dist/core/AccountFollowMeOrchestrator.js +4 -0
- package/dist/core/AccountFollowMeOrchestrator.js.map +1 -1
- package/dist/core/AppMediaStore.d.ts.map +1 -1
- package/dist/core/AppMediaStore.js +3 -0
- package/dist/core/AppMediaStore.js.map +1 -1
- package/dist/core/BackupManager.d.ts.map +1 -1
- package/dist/core/BackupManager.js +2 -0
- package/dist/core/BackupManager.js.map +1 -1
- package/dist/core/ClaudeCliIntelligenceProvider.d.ts.map +1 -1
- package/dist/core/ClaudeCliIntelligenceProvider.js +11 -3
- package/dist/core/ClaudeCliIntelligenceProvider.js.map +1 -1
- package/dist/core/ClaudeKeyHealth.d.ts +141 -0
- package/dist/core/ClaudeKeyHealth.d.ts.map +1 -0
- package/dist/core/ClaudeKeyHealth.js +467 -0
- package/dist/core/ClaudeKeyHealth.js.map +1 -0
- package/dist/core/CodexTaskContinuationStore.d.ts.map +1 -1
- package/dist/core/CodexTaskContinuationStore.js +7 -0
- package/dist/core/CodexTaskContinuationStore.js.map +1 -1
- package/dist/core/CoherenceJournal.d.ts +1 -1
- package/dist/core/CoherenceJournal.d.ts.map +1 -1
- package/dist/core/CoherenceJournal.js +11 -2
- package/dist/core/CoherenceJournal.js.map +1 -1
- package/dist/core/Config.d.ts +8 -0
- package/dist/core/Config.d.ts.map +1 -1
- package/dist/core/Config.js +26 -0
- package/dist/core/Config.js.map +1 -1
- package/dist/core/CredentialSwapExecutor.d.ts.map +1 -1
- package/dist/core/CredentialSwapExecutor.js +10 -0
- package/dist/core/CredentialSwapExecutor.js.map +1 -1
- package/dist/core/DecisionQualityRecorderImpl.d.ts.map +1 -1
- package/dist/core/DecisionQualityRecorderImpl.js +6 -0
- package/dist/core/DecisionQualityRecorderImpl.js.map +1 -1
- package/dist/core/DiscoveryEvaluator.d.ts.map +1 -1
- package/dist/core/DiscoveryEvaluator.js +4 -0
- package/dist/core/DiscoveryEvaluator.js.map +1 -1
- package/dist/core/IdentityReannounceClaimant.d.ts.map +1 -1
- package/dist/core/IdentityReannounceClaimant.js +4 -0
- package/dist/core/IdentityReannounceClaimant.js.map +1 -1
- package/dist/core/IntelligenceRouter.d.ts.map +1 -1
- package/dist/core/IntelligenceRouter.js +9 -0
- package/dist/core/IntelligenceRouter.js.map +1 -1
- package/dist/core/JournalSyncApplier.d.ts +1 -0
- package/dist/core/JournalSyncApplier.d.ts.map +1 -1
- package/dist/core/JournalSyncApplier.js +48 -0
- package/dist/core/JournalSyncApplier.js.map +1 -1
- package/dist/core/LeaseCoordinator.d.ts +4 -0
- package/dist/core/LeaseCoordinator.d.ts.map +1 -1
- package/dist/core/LeaseCoordinator.js +64 -1
- package/dist/core/LeaseCoordinator.js.map +1 -1
- package/dist/core/MachinePoolRegistry.d.ts +8 -0
- package/dist/core/MachinePoolRegistry.d.ts.map +1 -1
- package/dist/core/MachinePoolRegistry.js +25 -2
- package/dist/core/MachinePoolRegistry.js.map +1 -1
- package/dist/core/MessagingToneGate.d.ts +11 -7
- package/dist/core/MessagingToneGate.d.ts.map +1 -1
- package/dist/core/MessagingToneGate.js +15 -1
- package/dist/core/MessagingToneGate.js.map +1 -1
- package/dist/core/MobileDeviceKeys.d.ts +10 -0
- package/dist/core/MobileDeviceKeys.d.ts.map +1 -1
- package/dist/core/MobileDeviceKeys.js +17 -0
- package/dist/core/MobileDeviceKeys.js.map +1 -1
- package/dist/core/MultiMachineCoordinator.d.ts +12 -0
- package/dist/core/MultiMachineCoordinator.d.ts.map +1 -1
- package/dist/core/MultiMachineCoordinator.js +115 -3
- package/dist/core/MultiMachineCoordinator.js.map +1 -1
- package/dist/core/MutualSshRuntime.d.ts +1 -0
- package/dist/core/MutualSshRuntime.d.ts.map +1 -1
- package/dist/core/MutualSshRuntime.js +17 -1
- package/dist/core/MutualSshRuntime.js.map +1 -1
- package/dist/core/ObservedEndpointTracker.d.ts +1 -0
- package/dist/core/ObservedEndpointTracker.d.ts.map +1 -1
- package/dist/core/ObservedEndpointTracker.js +17 -0
- package/dist/core/ObservedEndpointTracker.js.map +1 -1
- package/dist/core/OverloadShedPlanner.d.ts +63 -7
- package/dist/core/OverloadShedPlanner.d.ts.map +1 -1
- package/dist/core/OverloadShedPlanner.js +177 -38
- package/dist/core/OverloadShedPlanner.js.map +1 -1
- package/dist/core/OwnershipApplier.d.ts.map +1 -1
- package/dist/core/OwnershipApplier.js +7 -0
- package/dist/core/OwnershipApplier.js.map +1 -1
- package/dist/core/OwnershipReconciler.d.ts +11 -0
- package/dist/core/OwnershipReconciler.d.ts.map +1 -1
- package/dist/core/OwnershipReconciler.js +32 -9
- package/dist/core/OwnershipReconciler.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +12 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +97 -5
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/PrHandLease.d.ts.map +1 -1
- package/dist/core/PrHandLease.js +2 -0
- package/dist/core/PrHandLease.js.map +1 -1
- package/dist/core/ProactiveSwapMonitor.d.ts.map +1 -1
- package/dist/core/ProactiveSwapMonitor.js +7 -0
- package/dist/core/ProactiveSwapMonitor.js.map +1 -1
- package/dist/core/ProjectRoundExecution.d.ts.map +1 -1
- package/dist/core/ProjectRoundExecution.js +3 -2
- package/dist/core/ProjectRoundExecution.js.map +1 -1
- package/dist/core/QueueDrainLoop.d.ts +7 -0
- package/dist/core/QueueDrainLoop.d.ts.map +1 -1
- package/dist/core/QueueDrainLoop.js +37 -1
- package/dist/core/QueueDrainLoop.js.map +1 -1
- package/dist/core/RebalancePlanner.d.ts +1 -0
- package/dist/core/RebalancePlanner.d.ts.map +1 -1
- package/dist/core/RebalancePlanner.js +1 -1
- package/dist/core/RebalancePlanner.js.map +1 -1
- package/dist/core/RemoteAckStore.d.ts.map +1 -1
- package/dist/core/RemoteAckStore.js +4 -0
- package/dist/core/RemoteAckStore.js.map +1 -1
- package/dist/core/ReplicatedStoreReconcilerWiring.d.ts.map +1 -1
- package/dist/core/ReplicatedStoreReconcilerWiring.js +1 -0
- package/dist/core/ReplicatedStoreReconcilerWiring.js.map +1 -1
- package/dist/core/SecretSync.d.ts +1 -0
- package/dist/core/SecretSync.d.ts.map +1 -1
- package/dist/core/SecretSync.js +16 -0
- package/dist/core/SecretSync.js.map +1 -1
- package/dist/core/SessionDrainRunner.d.ts +10 -1
- package/dist/core/SessionDrainRunner.d.ts.map +1 -1
- package/dist/core/SessionDrainRunner.js +60 -3
- package/dist/core/SessionDrainRunner.js.map +1 -1
- package/dist/core/SessionManager.d.ts +11 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +125 -14
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/SessionPoolFailoverRunner.d.ts.map +1 -1
- package/dist/core/SessionPoolFailoverRunner.js +4 -0
- package/dist/core/SessionPoolFailoverRunner.js.map +1 -1
- package/dist/core/SleepWakeDetector.d.ts.map +1 -1
- package/dist/core/SleepWakeDetector.js +10 -0
- package/dist/core/SleepWakeDetector.js.map +1 -1
- package/dist/core/StageAdvancer.d.ts +19 -0
- package/dist/core/StageAdvancer.d.ts.map +1 -1
- package/dist/core/StageAdvancer.js +51 -1
- package/dist/core/StageAdvancer.js.map +1 -1
- package/dist/core/SubscriptionReloginStore.d.ts.map +1 -1
- package/dist/core/SubscriptionReloginStore.js +10 -1
- package/dist/core/SubscriptionReloginStore.js.map +1 -1
- package/dist/core/TopicPinMutation.d.ts.map +1 -1
- package/dist/core/TopicPinMutation.js +5 -0
- package/dist/core/TopicPinMutation.js.map +1 -1
- package/dist/core/UnjustifiedStopGate.d.ts.map +1 -1
- package/dist/core/UnjustifiedStopGate.js +22 -0
- package/dist/core/UnjustifiedStopGate.js.map +1 -1
- package/dist/core/WindowRunCadenceExecutor.d.ts.map +1 -1
- package/dist/core/WindowRunCadenceExecutor.js +20 -0
- package/dist/core/WindowRunCadenceExecutor.js.map +1 -1
- package/dist/core/WriteDomainRegistry.d.ts.map +1 -1
- package/dist/core/WriteDomainRegistry.js +12 -0
- package/dist/core/WriteDomainRegistry.js.map +1 -1
- package/dist/core/claudeChildAuth.d.ts +68 -0
- package/dist/core/claudeChildAuth.d.ts.map +1 -0
- package/dist/core/claudeChildAuth.js +173 -0
- package/dist/core/claudeChildAuth.js.map +1 -0
- package/dist/core/claudeKeyProbe.d.ts +23 -0
- package/dist/core/claudeKeyProbe.d.ts.map +1 -0
- package/dist/core/claudeKeyProbe.js +68 -0
- package/dist/core/claudeKeyProbe.js.map +1 -0
- package/dist/core/codexDeviceLimitWiring.d.ts.map +1 -1
- package/dist/core/codexDeviceLimitWiring.js +12 -0
- package/dist/core/codexDeviceLimitWiring.js.map +1 -1
- package/dist/core/deliverToConversation.d.ts.map +1 -1
- package/dist/core/deliverToConversation.js +11 -0
- package/dist/core/deliverToConversation.js.map +1 -1
- package/dist/core/leaseMediumSelection.d.ts +8 -0
- package/dist/core/leaseMediumSelection.d.ts.map +1 -1
- package/dist/core/leaseMediumSelection.js +17 -0
- package/dist/core/leaseMediumSelection.js.map +1 -1
- package/dist/core/meteredCallEntry.d.ts.map +1 -1
- package/dist/core/meteredCallEntry.js +21 -0
- package/dist/core/meteredCallEntry.js.map +1 -1
- package/dist/core/nobodyPollingActuator.d.ts.map +1 -1
- package/dist/core/nobodyPollingActuator.js +5 -0
- package/dist/core/nobodyPollingActuator.js.map +1 -1
- package/dist/core/operatorSurfaceReferral.d.ts +18 -0
- package/dist/core/operatorSurfaceReferral.d.ts.map +1 -0
- package/dist/core/operatorSurfaceReferral.js +32 -0
- package/dist/core/operatorSurfaceReferral.js.map +1 -0
- package/dist/core/ownershipFollowsLiveWork.d.ts.map +1 -1
- package/dist/core/ownershipFollowsLiveWork.js +10 -1
- package/dist/core/ownershipFollowsLiveWork.js.map +1 -1
- package/dist/core/poolReadiness.d.ts +67 -0
- package/dist/core/poolReadiness.d.ts.map +1 -0
- package/dist/core/poolReadiness.js +156 -0
- package/dist/core/poolReadiness.js.map +1 -0
- package/dist/core/quietTopicScanner.d.ts +39 -0
- package/dist/core/quietTopicScanner.d.ts.map +1 -0
- package/dist/core/quietTopicScanner.js +57 -0
- package/dist/core/quietTopicScanner.js.map +1 -0
- package/dist/core/rebalanceProof.d.ts +114 -0
- package/dist/core/rebalanceProof.d.ts.map +1 -0
- package/dist/core/rebalanceProof.js +192 -0
- package/dist/core/rebalanceProof.js.map +1 -0
- package/dist/core/types.d.ts +23 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worktreeDirtyCheck.d.ts.map +1 -1
- package/dist/core/worktreeDirtyCheck.js +2 -0
- package/dist/core/worktreeDirtyCheck.js.map +1 -1
- package/dist/data/stageBCertifiedSet.d.ts +9 -0
- package/dist/data/stageBCertifiedSet.d.ts.map +1 -1
- package/dist/data/stageBCertifiedSet.js +12 -0
- package/dist/data/stageBCertifiedSet.js.map +1 -1
- package/dist/data/standards-guard-index.json +1 -1
- package/dist/data/standards-guard-index.meta.json +2 -2
- package/dist/data/standards-registry.meta.json +1 -1
- package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
- package/dist/lifeline/TelegramLifeline.js +17 -3
- package/dist/lifeline/TelegramLifeline.js.map +1 -1
- package/dist/messaging/attentionHubPolicy.d.ts.map +1 -1
- package/dist/messaging/attentionHubPolicy.js +1 -0
- package/dist/messaging/attentionHubPolicy.js.map +1 -1
- package/dist/monitoring/AgentWorktreeReaper.d.ts.map +1 -1
- package/dist/monitoring/AgentWorktreeReaper.js +15 -0
- package/dist/monitoring/AgentWorktreeReaper.js.map +1 -1
- package/dist/monitoring/ApprenticeshipCycleSlaMonitor.d.ts.map +1 -1
- package/dist/monitoring/ApprenticeshipCycleSlaMonitor.js +18 -9
- package/dist/monitoring/ApprenticeshipCycleSlaMonitor.js.map +1 -1
- package/dist/monitoring/CodexArmSessionSweeper.d.ts.map +1 -1
- package/dist/monitoring/CodexArmSessionSweeper.js +11 -0
- package/dist/monitoring/CodexArmSessionSweeper.js.map +1 -1
- package/dist/monitoring/CrashLoopPauser.d.ts.map +1 -1
- package/dist/monitoring/CrashLoopPauser.js +8 -0
- package/dist/monitoring/CrashLoopPauser.js.map +1 -1
- package/dist/monitoring/DegradationReporter.d.ts.map +1 -1
- package/dist/monitoring/DegradationReporter.js +7 -1
- package/dist/monitoring/DegradationReporter.js.map +1 -1
- package/dist/monitoring/DegradedTmuxGuard.d.ts +2 -0
- package/dist/monitoring/DegradedTmuxGuard.d.ts.map +1 -1
- package/dist/monitoring/DegradedTmuxGuard.js +14 -0
- package/dist/monitoring/DegradedTmuxGuard.js.map +1 -1
- package/dist/monitoring/DurableOutputScrubber.d.ts.map +1 -1
- package/dist/monitoring/DurableOutputScrubber.js +7 -0
- package/dist/monitoring/DurableOutputScrubber.js.map +1 -1
- package/dist/monitoring/DurableVaultSession.d.ts.map +1 -1
- package/dist/monitoring/DurableVaultSession.js +15 -0
- package/dist/monitoring/DurableVaultSession.js.map +1 -1
- package/dist/monitoring/ExternalHogSentinel.d.ts +2 -0
- package/dist/monitoring/ExternalHogSentinel.d.ts.map +1 -1
- package/dist/monitoring/ExternalHogSentinel.js +27 -1
- package/dist/monitoring/ExternalHogSentinel.js.map +1 -1
- package/dist/monitoring/FailureLedger.d.ts.map +1 -1
- package/dist/monitoring/FailureLedger.js +38 -1
- package/dist/monitoring/FailureLedger.js.map +1 -1
- package/dist/monitoring/FeatureEvidenceLog.d.ts +5 -0
- package/dist/monitoring/FeatureEvidenceLog.d.ts.map +1 -1
- package/dist/monitoring/FeatureEvidenceLog.js +25 -0
- package/dist/monitoring/FeatureEvidenceLog.js.map +1 -1
- package/dist/monitoring/GeminiCapacityEscalationMonitor.d.ts.map +1 -1
- package/dist/monitoring/GeminiCapacityEscalationMonitor.js +20 -2
- package/dist/monitoring/GeminiCapacityEscalationMonitor.js.map +1 -1
- package/dist/monitoring/GeminiLoopRunner.d.ts.map +1 -1
- package/dist/monitoring/GeminiLoopRunner.js +11 -1
- package/dist/monitoring/GeminiLoopRunner.js.map +1 -1
- package/dist/monitoring/GreenPrAutoMerger.d.ts.map +1 -1
- package/dist/monitoring/GreenPrAutoMerger.js +11 -0
- package/dist/monitoring/GreenPrAutoMerger.js.map +1 -1
- package/dist/monitoring/GrowthDigestPublisher.d.ts.map +1 -1
- package/dist/monitoring/GrowthDigestPublisher.js +16 -0
- package/dist/monitoring/GrowthDigestPublisher.js.map +1 -1
- package/dist/monitoring/GrowthMilestoneAnalyst.d.ts +3 -0
- package/dist/monitoring/GrowthMilestoneAnalyst.d.ts.map +1 -1
- package/dist/monitoring/GrowthMilestoneAnalyst.js +45 -1
- package/dist/monitoring/GrowthMilestoneAnalyst.js.map +1 -1
- package/dist/monitoring/McpProcessReaper.d.ts +2 -0
- package/dist/monitoring/McpProcessReaper.d.ts.map +1 -1
- package/dist/monitoring/McpProcessReaper.js +32 -0
- package/dist/monitoring/McpProcessReaper.js.map +1 -1
- package/dist/monitoring/MissingLoginSessionDetector.d.ts +2 -1
- package/dist/monitoring/MissingLoginSessionDetector.d.ts.map +1 -1
- package/dist/monitoring/MissingLoginSessionDetector.js +23 -0
- package/dist/monitoring/MissingLoginSessionDetector.js.map +1 -1
- package/dist/monitoring/OrchestratorPoller.d.ts +1 -0
- package/dist/monitoring/OrchestratorPoller.d.ts.map +1 -1
- package/dist/monitoring/OrchestratorPoller.js +13 -0
- package/dist/monitoring/OrchestratorPoller.js.map +1 -1
- package/dist/monitoring/OrphanedWorkSentinel.d.ts.map +1 -1
- package/dist/monitoring/OrphanedWorkSentinel.js +7 -0
- package/dist/monitoring/OrphanedWorkSentinel.js.map +1 -1
- package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
- package/dist/monitoring/PresenceProxy.js +9 -1
- package/dist/monitoring/PresenceProxy.js.map +1 -1
- package/dist/monitoring/ProcessFootprintMonitor.d.ts.map +1 -1
- package/dist/monitoring/ProcessFootprintMonitor.js +20 -2
- package/dist/monitoring/ProcessFootprintMonitor.js.map +1 -1
- package/dist/monitoring/PromiseBeacon.d.ts.map +1 -1
- package/dist/monitoring/PromiseBeacon.js +20 -0
- package/dist/monitoring/PromiseBeacon.js.map +1 -1
- package/dist/monitoring/ReleaseReadinessSentinel.d.ts +2 -0
- package/dist/monitoring/ReleaseReadinessSentinel.d.ts.map +1 -1
- package/dist/monitoring/ReleaseReadinessSentinel.js +26 -0
- package/dist/monitoring/ReleaseReadinessSentinel.js.map +1 -1
- package/dist/monitoring/RopeHealthMonitor.d.ts.map +1 -1
- package/dist/monitoring/RopeHealthMonitor.js +35 -1
- package/dist/monitoring/RopeHealthMonitor.js.map +1 -1
- package/dist/monitoring/SentinelNotifier.d.ts.map +1 -1
- package/dist/monitoring/SentinelNotifier.js +16 -0
- package/dist/monitoring/SentinelNotifier.js.map +1 -1
- package/dist/monitoring/SessionReaper.d.ts.map +1 -1
- package/dist/monitoring/SessionReaper.js +11 -2
- package/dist/monitoring/SessionReaper.js.map +1 -1
- package/dist/monitoring/SingleMachineFailoverGapDetector.d.ts +2 -0
- package/dist/monitoring/SingleMachineFailoverGapDetector.d.ts.map +1 -1
- package/dist/monitoring/SingleMachineFailoverGapDetector.js +20 -0
- package/dist/monitoring/SingleMachineFailoverGapDetector.js.map +1 -1
- package/dist/monitoring/SpeakerElection.d.ts.map +1 -1
- package/dist/monitoring/SpeakerElection.js +8 -0
- package/dist/monitoring/SpeakerElection.js.map +1 -1
- package/dist/monitoring/StrandedTopicSentinel.d.ts +3 -0
- package/dist/monitoring/StrandedTopicSentinel.d.ts.map +1 -1
- package/dist/monitoring/StrandedTopicSentinel.js +33 -0
- package/dist/monitoring/StrandedTopicSentinel.js.map +1 -1
- package/dist/native/InstarWedgeCanary.app/Contents/MacOS/InstarWedgeCanary +0 -0
- package/dist/native/instar-desktop-host +0 -0
- package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.d.ts.map +1 -1
- package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.js +5 -2
- package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.js.map +1 -1
- package/dist/recommended/RecommendedServicesLedger.d.ts +91 -0
- package/dist/recommended/RecommendedServicesLedger.d.ts.map +1 -0
- package/dist/recommended/RecommendedServicesLedger.js +193 -0
- package/dist/recommended/RecommendedServicesLedger.js.map +1 -0
- package/dist/recommended/RecommendedServicesReplicatedStore.d.ts +14 -0
- package/dist/recommended/RecommendedServicesReplicatedStore.d.ts.map +1 -0
- package/dist/recommended/RecommendedServicesReplicatedStore.js +34 -0
- package/dist/recommended/RecommendedServicesReplicatedStore.js.map +1 -0
- package/dist/recommended/legacyDeclines.d.ts +11 -0
- package/dist/recommended/legacyDeclines.d.ts.map +1 -0
- package/dist/recommended/legacyDeclines.js +17 -0
- package/dist/recommended/legacyDeclines.js.map +1 -0
- package/dist/recommended/serviceIds.d.ts +3 -0
- package/dist/recommended/serviceIds.d.ts.map +1 -0
- package/dist/recommended/serviceIds.js +6 -0
- package/dist/recommended/serviceIds.js.map +1 -0
- package/dist/scaffold/templates.d.ts +2 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +11 -1
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/scheduler/JobResultTriage.d.ts.map +1 -1
- package/dist/scheduler/JobResultTriage.js +10 -0
- package/dist/scheduler/JobResultTriage.js.map +1 -1
- package/dist/scheduler/JobScheduler.d.ts.map +1 -1
- package/dist/scheduler/JobScheduler.js +12 -0
- package/dist/scheduler/JobScheduler.js.map +1 -1
- package/dist/scheduler/MentorOnboardingRunner.d.ts +3 -0
- package/dist/scheduler/MentorOnboardingRunner.d.ts.map +1 -1
- package/dist/scheduler/MentorOnboardingRunner.js +24 -2
- package/dist/scheduler/MentorOnboardingRunner.js.map +1 -1
- package/dist/server/AgentServer.d.ts +2 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +78 -15
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/BootHealthBeacon.d.ts +3 -0
- package/dist/server/BootHealthBeacon.d.ts.map +1 -1
- package/dist/server/BootHealthBeacon.js +9 -0
- package/dist/server/BootHealthBeacon.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +12 -3
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/LifelineIngressGuard.d.ts.map +1 -1
- package/dist/server/LifelineIngressGuard.js +11 -0
- package/dist/server/LifelineIngressGuard.js.map +1 -1
- package/dist/server/PoolPollCache.d.ts +4 -0
- package/dist/server/PoolPollCache.d.ts.map +1 -1
- package/dist/server/PoolPollCache.js +33 -0
- package/dist/server/PoolPollCache.js.map +1 -1
- package/dist/server/machineRoutes.d.ts.map +1 -1
- package/dist/server/machineRoutes.js +6 -0
- package/dist/server/machineRoutes.js.map +1 -1
- package/dist/server/middleware.d.ts.map +1 -1
- package/dist/server/middleware.js +6 -0
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/mobileConsoleTicket.d.ts +113 -0
- package/dist/server/mobileConsoleTicket.d.ts.map +1 -0
- package/dist/server/mobileConsoleTicket.js +405 -0
- package/dist/server/mobileConsoleTicket.js.map +1 -0
- package/dist/server/mobileConversationRoutes.d.ts.map +1 -1
- package/dist/server/mobileConversationRoutes.js +20 -1
- package/dist/server/mobileConversationRoutes.js.map +1 -1
- package/dist/server/mobileMediaRoutes.d.ts.map +1 -1
- package/dist/server/mobileMediaRoutes.js +3 -0
- package/dist/server/mobileMediaRoutes.js.map +1 -1
- package/dist/server/mobilePairingRoutes.d.ts +8 -2
- package/dist/server/mobilePairingRoutes.d.ts.map +1 -1
- package/dist/server/mobilePairingRoutes.js +67 -6
- package/dist/server/mobilePairingRoutes.js.map +1 -1
- package/dist/server/mobileSessionTerminalRoutes.d.ts +128 -0
- package/dist/server/mobileSessionTerminalRoutes.d.ts.map +1 -0
- package/dist/server/mobileSessionTerminalRoutes.js +389 -0
- package/dist/server/mobileSessionTerminalRoutes.js.map +1 -0
- package/dist/server/recommendedServiceRoutes.d.ts +13 -0
- package/dist/server/recommendedServiceRoutes.d.ts.map +1 -0
- package/dist/server/recommendedServiceRoutes.js +49 -0
- package/dist/server/recommendedServiceRoutes.js.map +1 -0
- package/dist/server/routes.d.ts +2 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +215 -5
- package/dist/server/routes.js.map +1 -1
- package/dist/testing/selfActionRegistry.d.ts.map +1 -1
- package/dist/testing/selfActionRegistry.js +44 -3
- package/dist/testing/selfActionRegistry.js.map +1 -1
- package/dist/threadline/A2ACheckInProxy.d.ts.map +1 -1
- package/dist/threadline/A2ACheckInProxy.js +26 -15
- package/dist/threadline/A2ACheckInProxy.js.map +1 -1
- package/dist/threadline/AgentTrustManager.d.ts.map +1 -1
- package/dist/threadline/AgentTrustManager.js +3 -0
- package/dist/threadline/AgentTrustManager.js.map +1 -1
- package/dist/threadline/InboundIdLedger.d.ts.map +1 -1
- package/dist/threadline/InboundIdLedger.js +18 -1
- package/dist/threadline/InboundIdLedger.js.map +1 -1
- package/dist/threadline/NegotiatorGate.d.ts.map +1 -1
- package/dist/threadline/NegotiatorGate.js +11 -0
- package/dist/threadline/NegotiatorGate.js.map +1 -1
- package/dist/threadline/PipeSessionSpawner.d.ts.map +1 -1
- package/dist/threadline/PipeSessionSpawner.js +8 -0
- package/dist/threadline/PipeSessionSpawner.js.map +1 -1
- package/dist/threadline/ThreadlineRouter.d.ts.map +1 -1
- package/dist/threadline/ThreadlineRouter.js +13 -0
- package/dist/threadline/ThreadlineRouter.js.map +1 -1
- package/dist/threadline/pairingReplicationWiring.d.ts.map +1 -1
- package/dist/threadline/pairingReplicationWiring.js +9 -0
- package/dist/threadline/pairingReplicationWiring.js.map +1 -1
- package/dist/threadline/relayForward.d.ts.map +1 -1
- package/dist/threadline/relayForward.js +13 -2
- package/dist/threadline/relayForward.js.map +1 -1
- package/dist/threadline/relayUnknownSenderTrust.d.ts +0 -9
- package/dist/threadline/relayUnknownSenderTrust.d.ts.map +1 -1
- package/dist/threadline/relayUnknownSenderTrust.js +16 -0
- package/dist/threadline/relayUnknownSenderTrust.js.map +1 -1
- package/package.json +1 -1
- package/scripts/check-constitution-pairing.mjs +273 -0
- package/scripts/safe-merge.mjs +9 -0
- package/src/data/builtin-manifest.json +103 -103
- package/src/data/feature-ladders.json +113 -113
- package/src/data/stageBCertifiedSet.ts +12 -0
- package/src/data/standards-guard-index.json +1 -1
- package/src/data/standards-guard-index.meta.json +2 -2
- package/src/data/standards-registry.meta.json +1 -1
- package/src/data/state-coherence-registry.json +18 -0
- package/src/scaffold/templates.ts +12 -1
- package/upgrades/1.3.1650.md +105 -0
- package/upgrades/1.3.1651.md +30 -0
- package/upgrades/mobile-console-device-signin.eli16.md +5 -0
- package/upgrades/side-effects/cloud-key-internal-calls.md +116 -0
- package/upgrades/side-effects/constitution-alignment.eli16.md +11 -0
- package/upgrades/side-effects/constitution-alignment.md +69 -0
- package/upgrades/side-effects/feature-evidence-recording.eli16.md +3 -0
- package/upgrades/side-effects/feature-evidence-recording.md +66 -0
- package/upgrades/side-effects/feedback-reroute-admission-parity.md +77 -0
- package/upgrades/side-effects/mobile-console-device-signin.md +102 -0
- package/upgrades/side-effects/mobile-native-session-screen.md +88 -0
- package/upgrades/side-effects/operator-needs-first-screen.md +87 -0
- package/upgrades/side-effects/recommended-services-choices.md +50 -0
- package/upgrades/side-effects/rerouted-lifetime-active-process.md +63 -0
- package/upgrades/side-effects/session-pool-default-on.md +53 -0
- package/upgrades/side-effects/session-pool-rebalancing-finish.md +151 -0
- package/upgrades/side-effects/undated-resurfacer-e2e-wait.eli16.md +5 -0
- package/upgrades/side-effects/undated-resurfacer-e2e-wait.md +9 -0
package/dist/commands/server.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* the boot-time TCC-protected path detection + /guards row (see the
|
|
4
4
|
* TccProtectedPathGuard block beside the worktree detector).
|
|
5
5
|
*/
|
|
6
|
+
import { configureClaudeChildAuth, sweepClaudeAuthEnvFiles } from '../core/claudeChildAuth.js';
|
|
6
7
|
import { slackHistoryLabel } from '../messaging/slack/threadHistoryLabel.js';
|
|
7
8
|
import { readPairingOwnerName } from '../threadline/pairingOwnerName.js';
|
|
8
9
|
import { buildThrowawayJobGuard, checkThrowawayExpiry, describeExpiry, takeLastAutoStartRefusal, throwawayStartupDecision } from '../core/ThrowawayAgentGuard.js';
|
|
@@ -54,14 +55,17 @@ import { setAspClassifierRef, getAspClassifierRef } from '../core/aspClassifierR
|
|
|
54
55
|
import { resolveInboundTelegramMessageId, resolveSignedByAgent, operatorAutoBindPermitted } from '../messaging/shared/signedInbound.js';
|
|
55
56
|
import { verifiedEntityName } from '../messaging/shared/channelIdentity.js';
|
|
56
57
|
import { StandDownRegistry } from '../core/StandDownRegistry.js';
|
|
57
|
-
import { getActiveOverloadShedPlanner } from '../core/OverloadShedPlanner.js';
|
|
58
|
+
import { getActiveOverloadShedPlanner, getMoveAftercare } from '../core/OverloadShedPlanner.js';
|
|
59
|
+
import { QuietTopicScanner } from '../core/quietTopicScanner.js';
|
|
60
|
+
import { RebalanceProofRunner, getActiveRebalanceProof, proofSpawnBrief, setActiveRebalanceProof, setActiveRebalanceProofStore } from '../core/rebalanceProof.js';
|
|
61
|
+
import { rebalanceProofState } from '../core/StageAdvancer.js';
|
|
58
62
|
import { buildHandoffContinuationInstruction } from '../core/handoffContinuation.js';
|
|
59
63
|
import { BASELINE_PROCESS_PATTERNS } from '../core/baselineProcessPatterns.js';
|
|
60
64
|
import { StandDownAudit } from '../core/StandDownAudit.js';
|
|
61
65
|
import { resolveStandardsRegistry } from '../core/standardsRegistryPath.js';
|
|
62
66
|
import { chunkLiteralForTmux, buildLiteralSendArgs } from '../core/tmuxLiteralSend.js';
|
|
63
67
|
import { parseStandardsRegistry } from '../core/StandardsRegistryParser.js';
|
|
64
|
-
import { loadConfig, ensureStateDir, detectTmuxPath, detectGeminiPath } from '../core/Config.js';
|
|
68
|
+
import { loadConfig, ensureStateDir, detectTmuxPath, detectGeminiPath, detectClaudePath, readConfiguredAnthropicKey } from '../core/Config.js';
|
|
65
69
|
import { handleProcessLevelError } from '../core/uncaughtExceptionPolicy.js';
|
|
66
70
|
import { planInboundLossNotices } from '../core/inboundLossRouting.js';
|
|
67
71
|
import { heartbeatFreshEnoughToRerecord } from '../core/MachineHeartbeat.js';
|
|
@@ -75,6 +79,7 @@ import { SingleInstanceLock, installReleaseHandlers } from '../core/SingleInstan
|
|
|
75
79
|
import { resolveDevAgentGate, resolveStateSyncStores } from '../core/devAgentGate.js';
|
|
76
80
|
import { JOB_LEASE_POOL_AUTHORITY_READY } from '../scheduler/JobLeaseClaimStore.js';
|
|
77
81
|
import { resolveRelayUnknownSenderTrustMode } from '../threadline/relayUnknownSenderTrust.js';
|
|
82
|
+
import { featureEvidence } from '../monitoring/FeatureEvidenceLog.js';
|
|
78
83
|
import { resolveEncryptToPinnedMode, encryptToPinnedModeName } from '../threadline/encryptToPinned.js';
|
|
79
84
|
import { resolveRefuseDowngradeMode } from '../threadline/refuseDowngrade.js';
|
|
80
85
|
import { MarkedPairingInviteFlow } from '../threadline/PairingPendingAcceptMarkers.js';
|
|
@@ -231,7 +236,7 @@ import { AutonomousEvolution } from '../core/AutonomousEvolution.js';
|
|
|
231
236
|
import { DispatchScopeEnforcer } from '../core/DispatchScopeEnforcer.js';
|
|
232
237
|
import { TrustRecovery } from '../core/TrustRecovery.js';
|
|
233
238
|
import { DegradationReporter } from '../monitoring/DegradationReporter.js';
|
|
234
|
-
import { reportLeaseMediumSelection, selectLeaseMedium } from '../core/leaseMediumSelection.js';
|
|
239
|
+
import { gitLeaseHasNoRemote, reportLeaseMediumSelection, selectLeaseMedium } from '../core/leaseMediumSelection.js';
|
|
235
240
|
import { HumanAsDetectorLog, observeInboundMessage } from '../monitoring/HumanAsDetectorLog.js';
|
|
236
241
|
import { creditUsherOnMiss } from '../core/UsherActedCorrelator.js';
|
|
237
242
|
import { resolveStableNodeBinary } from '../utils/resolveNodeBinary.js';
|
|
@@ -634,6 +639,8 @@ let _inboundQueue = null;
|
|
|
634
639
|
// Late-bound self-capacity refresh. The heartbeat writer is constructed before
|
|
635
640
|
// the durable inbound queue, whose live handle is one of the advertised fields.
|
|
636
641
|
let _refreshPoolHeartbeat = () => { };
|
|
642
|
+
/** Boot-cached takeover reading for the pool readiness report; never read from /health. */
|
|
643
|
+
let _takeoverReadiness = { state: 'unknown', reason: 'only a real takeover proves this' };
|
|
637
644
|
// Module-level handle for the machine-coherence guard (machine-coherence-guard
|
|
638
645
|
// §6) so `GET /pool/machine-coherence` can read the sentinel constructed deep in
|
|
639
646
|
// the mesh peer-presence wiring. Null when the guard is dark (route 503s).
|
|
@@ -646,6 +653,9 @@ let _singleMachineFailoverGap = null;
|
|
|
646
653
|
// `GET /pool/missing-login` can read the detector constructed deep in the mesh
|
|
647
654
|
// peer-presence wiring. Null when the guard is dark (route 503s).
|
|
648
655
|
let _missingLoginSession = null;
|
|
656
|
+
// The journal compaction pass runs at boot, before the evidence log is wired by
|
|
657
|
+
// AgentServer; its row is held here and written straight after that construction.
|
|
658
|
+
let _pendingCompactionEvidence = null;
|
|
649
659
|
// Module-level handle for the SessionPoolFailoverRunner driver (§Rollout, Track H)
|
|
650
660
|
// so `GET /session-pool/failover-runner` can read its status(). Null when the
|
|
651
661
|
// runner is dark (dev-gated) — the route 503s. Constructed inside the rollout-gate
|
|
@@ -808,6 +818,8 @@ let _pinPlacementMetadata = null;
|
|
|
808
818
|
let _ws13SustainedOnline = null;
|
|
809
819
|
/** Cross-machine secret-sync (spec Phase 4): route-facing handle (push lever + read-only status). */
|
|
810
820
|
let _secretSyncHandle = null;
|
|
821
|
+
/** The boot-time escrow result, recorded as evidence once the evidence log is wired. Flags only, no key material. */
|
|
822
|
+
let _recoveryEscrowEvidence = null;
|
|
811
823
|
/** Pool Dashboard Streaming (POOL-DASHBOARD-STREAM-SPEC §2.3): shared single-use
|
|
812
824
|
* ticket store — minted by the `pool-stream-ticket` mesh verb, consumed by the
|
|
813
825
|
* WebSocketManager's /pool-stream upgrade. Constructed in the mesh-setup block. */
|
|
@@ -987,6 +999,12 @@ let _sessionRefresh = null;
|
|
|
987
999
|
let _ownershipReconciler = null;
|
|
988
1000
|
/** trustworthy-machine-load D: the overload-shed evaluation timer (cleared at shutdown). */
|
|
989
1001
|
let _overloadShedTimer = null;
|
|
1002
|
+
/** This machine's rebalance proof store (session-pool-rebalancing-finish): built with the rollout gate, read by the shed. */
|
|
1003
|
+
let _rebalanceProofStore = null;
|
|
1004
|
+
let _sessionPoolBuildIdentity = null;
|
|
1005
|
+
let _shedDrainInFlight = false;
|
|
1006
|
+
/** Topics in a shed drain: they journal as `reconcile`, because peers reject an unknown reason. */
|
|
1007
|
+
const _shedDrainTopics = new Set();
|
|
990
1008
|
// U4.2 stale-owner release — the evidence-upgraded Case C engine, hoisted so the
|
|
991
1009
|
// GET /pool/stale-owner-release route + the reconciler dep can reach it. Null
|
|
992
1010
|
// until the pool block constructs it (single-machine / dark → the route 503s).
|
|
@@ -1001,6 +1019,7 @@ let _spawnAdmission = null;
|
|
|
1001
1019
|
/** Native app conversations (mobile-native-conversations, increment 1) — late-bound for the replication observers. */
|
|
1002
1020
|
let _appConversationService = null;
|
|
1003
1021
|
let _ecosystemLedger = null;
|
|
1022
|
+
let _recommendedServicesLedger = null;
|
|
1004
1023
|
// trustworthy-machine-load C5: one fixed holding notice per topic per overload
|
|
1005
1024
|
// episode when EVERY machine refuses new work (30-min cooldown; the message
|
|
1006
1025
|
// itself is already in durable custody, this only tells the user why it waits).
|
|
@@ -2484,6 +2503,14 @@ getHubClassifierDeps) {
|
|
|
2484
2503
|
modelTier: clsDeps.modelTier,
|
|
2485
2504
|
});
|
|
2486
2505
|
const willAct = result.isCommand && !clsDeps.dryRun;
|
|
2506
|
+
// Same scope as the audit below: LLM-engaged verdicts, never the prefilter-skip bulk.
|
|
2507
|
+
if (result.source !== 'prefilter-skip') {
|
|
2508
|
+
featureEvidence.record('threadline.hubIntent', {
|
|
2509
|
+
kind: result.source === 'fail-open' ? 'error' : 'fired',
|
|
2510
|
+
reason: result.source === 'fail-open' ? 'classifier-fail-open' : result.isCommand ? (willAct ? 'swallow' : 'would-swallow') : 'would-pass',
|
|
2511
|
+
context: { topicId, dryRun: clsDeps.dryRun, source: result.source, intent: result.intent ?? null, confidence: result.confidence ?? null, targetTopicId: result.targetTopicId ?? null },
|
|
2512
|
+
});
|
|
2513
|
+
}
|
|
2487
2514
|
// Audit the soak: log LLM-engaged decisions (a prefilter-skip is the
|
|
2488
2515
|
// bulk of traffic and always a would-pass — skipping it cuts volume
|
|
2489
2516
|
// AND the message-preview privacy surface). Never gates the message.
|
|
@@ -2528,6 +2555,7 @@ getHubClassifierDeps) {
|
|
|
2528
2555
|
}
|
|
2529
2556
|
catch (err) {
|
|
2530
2557
|
console.warn(`[telegram] hub-command intercept error (fail-open): ${err instanceof Error ? err.message : err}`);
|
|
2558
|
+
featureEvidence.record('threadline.hubIntent', { kind: 'error', reason: 'intercept-threw-fail-open', context: { errorName: err instanceof Error ? err.name : 'unknown' } });
|
|
2531
2559
|
}
|
|
2532
2560
|
}
|
|
2533
2561
|
// ── Fix commands from notification messages ──────────────────────
|
|
@@ -2576,7 +2604,7 @@ getHubClassifierDeps) {
|
|
|
2576
2604
|
// mesh) instead of handling it locally. DARK (the default) skips this block
|
|
2577
2605
|
// entirely → byte-identical to single-machine dispatch. Any error falls back
|
|
2578
2606
|
// to the local path below (fail-safe). The live-transfer behavior is gated by
|
|
2579
|
-
// the staged rollout (StageAdvancer)
|
|
2607
|
+
// the staged rollout (StageAdvancer). Any stage past dark places for real, shadow included.
|
|
2580
2608
|
// SpawnAdmission TOCTOU guard (ownership-gated-spawn §3.1 item 2): stash the
|
|
2581
2609
|
// router's verdict for THIS message so the seam at the spawn callsites below
|
|
2582
2610
|
// CONSUMES it instead of re-resolving — the admission decision and the
|
|
@@ -3861,6 +3889,10 @@ export async function startServer(options) {
|
|
|
3861
3889
|
watchPaths: ['updates.autoApply', 'sessions.maxSessions', 'monitoring'],
|
|
3862
3890
|
});
|
|
3863
3891
|
liveConfig.start();
|
|
3892
|
+
// Every server-side `claude` child gets the configured sign-in key from here, read per call so a
|
|
3893
|
+
// restored key applies at once (spec cloud-key-internal-calls). Off: sessions.claudeChildAuth.enabled.
|
|
3894
|
+
configureClaudeChildAuth(() => liveConfig.get('sessions.claudeChildAuth.enabled', true) === false ? undefined : config.sessions?.anthropicApiKey, () => config.sessions?.anthropicBaseUrl);
|
|
3895
|
+
sweepClaudeAuthEnvFiles(config.stateDir);
|
|
3864
3896
|
// Threadline → Telegram bridge config — settings surface for the bridge
|
|
3865
3897
|
// module. Default-OFF auto-create ships from day one;
|
|
3866
3898
|
// see TelegramBridgeConfig for the policy.
|
|
@@ -4075,6 +4107,7 @@ export async function startServer(options) {
|
|
|
4075
4107
|
// covers the window on the fleet. D4-verified read-only (localhost-only inbound
|
|
4076
4108
|
// socket, zero outbound). Belt-and-suspenders, not a boot reorder.
|
|
4077
4109
|
let bootBeacon;
|
|
4110
|
+
let bootBeaconBindErrorCode = null;
|
|
4078
4111
|
if (resolveDevAgentGate(config.monitoring?.bootHealthBeacon?.enabled, config)) {
|
|
4079
4112
|
try {
|
|
4080
4113
|
bootBeacon = new BootHealthBeacon(config.port);
|
|
@@ -4086,6 +4119,7 @@ export async function startServer(options) {
|
|
|
4086
4119
|
// failure must NEVER block the server boot (the startupGrace bump still
|
|
4087
4120
|
// covers the health window). Logged here, not swallowed silently.
|
|
4088
4121
|
bootBeacon = undefined;
|
|
4122
|
+
bootBeaconBindErrorCode = err?.code ?? 'unknown';
|
|
4089
4123
|
console.error(' Boot health beacon failed to start (non-fatal):', err instanceof Error ? err.message : err);
|
|
4090
4124
|
}
|
|
4091
4125
|
}
|
|
@@ -4779,6 +4813,9 @@ export async function startServer(options) {
|
|
|
4779
4813
|
// docs/specs/ecosystem-idea-pipeline.md: inert registration; the store is injected below whenever the pipeline is on.
|
|
4780
4814
|
const { ECOSYSTEM_IDEAS_KIND_REGISTRATION } = await import('../ecosystem/EcosystemIdeasReplicatedStore.js');
|
|
4781
4815
|
replicatedKindRegistry.register(ECOSYSTEM_IDEAS_KIND_REGISTRATION);
|
|
4816
|
+
// docs/specs/recommended-services.md: a person's choices follow them across machines.
|
|
4817
|
+
const { RECOMMENDED_SERVICES_KIND_REGISTRATION } = await import('../recommended/RecommendedServicesReplicatedStore.js');
|
|
4818
|
+
replicatedKindRegistry.register(RECOMMENDED_SERVICES_KIND_REGISTRATION);
|
|
4782
4819
|
// mobile-native-conversations §4.8 — the `mobileDeviceKeyLedger` kind (inert registration; on
|
|
4783
4820
|
// whenever native app conversations are on, so a signed record can be checked on any machine).
|
|
4784
4821
|
const { DEVICE_KEY_LEDGER_KIND_REGISTRATION } = await import('../core/MobileDeviceKeyLedgerReplicatedStore.js');
|
|
@@ -4940,13 +4977,35 @@ export async function startServer(options) {
|
|
|
4940
4977
|
const compactionConfig = config.multiMachine?.coherenceJournal?.replication?.compaction;
|
|
4941
4978
|
if (compactionConfig?.run === true) {
|
|
4942
4979
|
const { ReplicatedJournalCompactor } = await import('../core/ReplicatedJournalCompactor.js');
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4980
|
+
try {
|
|
4981
|
+
const compaction = new ReplicatedJournalCompactor({
|
|
4982
|
+
stateDir: config.stateDir,
|
|
4983
|
+
registry: replicatedKindRegistry,
|
|
4984
|
+
enabled: true,
|
|
4985
|
+
dryRun: compactionConfig.dryRun ?? true,
|
|
4986
|
+
logger: (m) => console.log(pc.dim(` ${m}`)),
|
|
4987
|
+
}).run();
|
|
4988
|
+
_pendingCompactionEvidence = {
|
|
4989
|
+
kind: 'fired',
|
|
4990
|
+
reason: compaction.dryRun ? 'would-compact' : 'compacted',
|
|
4991
|
+
context: {
|
|
4992
|
+
dryRun: compaction.dryRun,
|
|
4993
|
+
filesCompacted: compaction.filesCompacted,
|
|
4994
|
+
originalRecords: compaction.originalRecords,
|
|
4995
|
+
compactedRecords: compaction.compactedRecords,
|
|
4996
|
+
bytesBefore: compaction.bytesBefore,
|
|
4997
|
+
bytesAfter: compaction.bytesAfter,
|
|
4998
|
+
},
|
|
4999
|
+
};
|
|
5000
|
+
}
|
|
5001
|
+
catch (compactionErr) {
|
|
5002
|
+
_pendingCompactionEvidence = {
|
|
5003
|
+
kind: 'error',
|
|
5004
|
+
reason: 'compaction-failed',
|
|
5005
|
+
context: { dryRun: compactionConfig.dryRun ?? true, errorName: compactionErr instanceof Error ? compactionErr.name : 'unknown' },
|
|
5006
|
+
};
|
|
5007
|
+
throw compactionErr;
|
|
5008
|
+
}
|
|
4950
5009
|
// A real run replaced streams atomically; rebuild from the committed files.
|
|
4951
5010
|
}
|
|
4952
5011
|
coherenceJournal.setReplicatedRecordCommitObserver((kind, entries) => {
|
|
@@ -4973,6 +5032,14 @@ export async function startServer(options) {
|
|
|
4973
5032
|
for (const e of entries)
|
|
4974
5033
|
_ecosystemLedger.ingestReplicated(e.data.event);
|
|
4975
5034
|
}
|
|
5035
|
+
// A person's choices: each row lands only when it verifies under the machine it names.
|
|
5036
|
+
if (kind === 'recommended-service-record' && _recommendedServicesLedger) {
|
|
5037
|
+
for (const e of entries) {
|
|
5038
|
+
const r = _recommendedServicesLedger.ingestReplicated(e.data.row);
|
|
5039
|
+
if (r === 'bad-signature' || r === 'unverifiable')
|
|
5040
|
+
console.warn(` [recommended-services] a replicated row was not accepted (${r})`);
|
|
5041
|
+
}
|
|
5042
|
+
}
|
|
4976
5043
|
// Device-key ledger rows: each lands only when it verifies under the pinned key of the machine it names.
|
|
4977
5044
|
if (kind === 'mobile-device-key-ledger-row' && _appConversationService?.deps.keyLedger) {
|
|
4978
5045
|
const ledger = _appConversationService.deps.keyLedger;
|
|
@@ -5088,6 +5155,11 @@ export async function startServer(options) {
|
|
|
5088
5155
|
const _appNativeOn = _isMobileNativeEnabled(config);
|
|
5089
5156
|
const _stateSyncStoresResolved = (() => {
|
|
5090
5157
|
let s = _stateSyncStoresBase ?? {};
|
|
5158
|
+
// On wherever the journal is live: a yes or no belongs to the person, not one machine
|
|
5159
|
+
// (docs/specs/recommended-services.md). Without the journal there is no applier, so it isn't advertised.
|
|
5160
|
+
const _recommendedServicesOn = !!coherenceJournal && _stateSyncStoresBase?.recommendedServices?.enabled !== false;
|
|
5161
|
+
if (_recommendedServicesOn)
|
|
5162
|
+
s = { ...s, recommendedServices: { enabled: true } };
|
|
5091
5163
|
if (_appNativeOn)
|
|
5092
5164
|
s = { ...s, appConversations: { enabled: true }, mobileDeviceKeyLedger: { enabled: true } };
|
|
5093
5165
|
if (resolveDevAgentGate(config.ecosystemIdeas?.enabled, config))
|
|
@@ -5098,7 +5170,7 @@ export async function startServer(options) {
|
|
|
5098
5170
|
s = { ...s, topicPins: { enabled: true } };
|
|
5099
5171
|
if (_staleOwnerReleaseResolved)
|
|
5100
5172
|
s = { ...s, topicClaimAnnotations: { enabled: true } };
|
|
5101
|
-
return _appNativeOn || _accountFollowMeEnabled || _pinReplicateEnabled || _staleOwnerReleaseResolved || _stateSyncStoresBase ? s : _stateSyncStoresBase;
|
|
5173
|
+
return _recommendedServicesOn || _appNativeOn || _accountFollowMeEnabled || _pinReplicateEnabled || _staleOwnerReleaseResolved || _stateSyncStoresBase ? s : _stateSyncStoresBase;
|
|
5102
5174
|
})();
|
|
5103
5175
|
// WS2 send-side: the generic journal-backed record emitter (the concrete emitter
|
|
5104
5176
|
// the per-store managers' emit hooks call). Needs the journal sink, the HLC clock,
|
|
@@ -5465,6 +5537,9 @@ export async function startServer(options) {
|
|
|
5465
5537
|
const leaseGitRef = leaseMedium.medium === 'local' ? undefined : gitSyncRef;
|
|
5466
5538
|
const leaseStoreName = leaseGitRef ? 'GitLeaseStore' : 'LocalLeaseStore';
|
|
5467
5539
|
coordinator.attachLeaseMediumProvider(() => ({ ...leaseMedium, store: leaseStoreName }));
|
|
5540
|
+
if (leaseGitRef && gitLeaseHasNoRemote(config.projectDir) === true) {
|
|
5541
|
+
_takeoverReadiness = { state: 'failing', reason: 'this machine uses the git lease with no git remote, so it cannot take over' };
|
|
5542
|
+
}
|
|
5468
5543
|
try {
|
|
5469
5544
|
// ── G1 fenced-lease integration (spec §6) ──────────────────
|
|
5470
5545
|
// The lease is the authority for awake/standby + the MeshRpc router-only
|
|
@@ -7682,6 +7757,7 @@ export async function startServer(options) {
|
|
|
7682
7757
|
// Never let a pauser fault take down the boot path or the interval.
|
|
7683
7758
|
clpLastError = err instanceof Error ? err.message : String(err);
|
|
7684
7759
|
console.error(pc.red(` CrashLoopPauser pass failed: ${clpLastError}`));
|
|
7760
|
+
featureEvidence.record('monitoring.crashLoopPauser', { kind: 'error', reason: 'pause pass failed', context: { dryRun: clpDryRun, errorName: err instanceof Error ? err.name : 'unknown' } });
|
|
7685
7761
|
}
|
|
7686
7762
|
};
|
|
7687
7763
|
const clpInitialDelay = clpCfg.initialPassDelayMs ?? 10 * 60_000;
|
|
@@ -8808,6 +8884,50 @@ export async function startServer(options) {
|
|
|
8808
8884
|
console.warn(` [app-conversations] wiring failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
8809
8885
|
}
|
|
8810
8886
|
}
|
|
8887
|
+
// docs/specs/recommended-services.md: built here so its rows replicate; no identity means no ledger, and the routes answer 503.
|
|
8888
|
+
try {
|
|
8889
|
+
const { loadMachineSigner, identityKeyLookup } = await import('../core/AppRecordSignatures.js');
|
|
8890
|
+
const { RecommendedServicesLedger } = await import('../recommended/RecommendedServicesLedger.js');
|
|
8891
|
+
const recRepl = await import('../recommended/RecommendedServicesReplicatedStore.js');
|
|
8892
|
+
const signer = loadMachineSigner(config.stateDir);
|
|
8893
|
+
if (signer) {
|
|
8894
|
+
const ledger = new RecommendedServicesLedger({ stateDir: config.stateDir, signer, keyLookup: identityKeyLookup(config.stateDir) });
|
|
8895
|
+
if (replicatedRecordEmitter) {
|
|
8896
|
+
const emitter = replicatedRecordEmitter;
|
|
8897
|
+
const emitRow = (row) => {
|
|
8898
|
+
const { outcome } = emitter.emit(recRepl.RECOMMENDED_SERVICES_STORE_KEY, recRepl.deriveRecommendedServiceRecordKey(row.eventId), recRepl.buildRecommendedServiceRecordData(row));
|
|
8899
|
+
if (outcome !== 'emitted')
|
|
8900
|
+
console.warn(` [recommended-services] a choice was not replicated yet (${outcome}); it is sent again at next boot`);
|
|
8901
|
+
};
|
|
8902
|
+
ledger.setReplicationHook(emitRow);
|
|
8903
|
+
ledger.setReplicating(_stateSyncStoresResolved?.recommendedServices?.enabled === true && config.multiMachine?.coherenceJournal?.replication?.enabled === true);
|
|
8904
|
+
// Rows written while the journal was off, or dropped by a rate cap, go out now.
|
|
8905
|
+
if (replicatedPeerStreamReader && cjOwnMachineId) {
|
|
8906
|
+
for (const row of ledger.all()) {
|
|
8907
|
+
if (row.machineId !== signer.machineId())
|
|
8908
|
+
continue;
|
|
8909
|
+
const rk = recRepl.deriveRecommendedServiceRecordKey(row.eventId);
|
|
8910
|
+
if (!replicatedPeerStreamReader.loadOriginRecords(recRepl.RECOMMENDED_SERVICES_STORE_KEY, rk).some((o) => o.origin === cjOwnMachineId))
|
|
8911
|
+
emitRow(row);
|
|
8912
|
+
}
|
|
8913
|
+
}
|
|
8914
|
+
}
|
|
8915
|
+
if (replicatedPeerStreamReader && cjOwnMachineId) {
|
|
8916
|
+
const reader = replicatedPeerStreamReader;
|
|
8917
|
+
for (const rk of reader.listRecordKeys(recRepl.RECOMMENDED_SERVICES_STORE_KEY)) {
|
|
8918
|
+
for (const r of reader.loadOriginRecords(recRepl.RECOMMENDED_SERVICES_STORE_KEY, rk)) {
|
|
8919
|
+
if (r.origin !== cjOwnMachineId)
|
|
8920
|
+
ledger.ingestReplicated(r.data.row);
|
|
8921
|
+
}
|
|
8922
|
+
}
|
|
8923
|
+
}
|
|
8924
|
+
_recommendedServicesLedger = ledger;
|
|
8925
|
+
}
|
|
8926
|
+
}
|
|
8927
|
+
catch (err) {
|
|
8928
|
+
// @silent-fallback-ok: reported; the routes answer 503 and nothing else depends on this
|
|
8929
|
+
console.warn(` [recommended-services] ledger wiring failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
8930
|
+
}
|
|
8811
8931
|
// docs/specs/ecosystem-idea-pipeline.md: the ledger is built here so its events replicate; AgentServer builds the service.
|
|
8812
8932
|
if (resolveDevAgentGate(config.ecosystemIdeas?.enabled, config)) {
|
|
8813
8933
|
try {
|
|
@@ -14068,9 +14188,26 @@ export async function startServer(options) {
|
|
|
14068
14188
|
if (replicatedRecordEmitter && _accountFollowMeEnabled) {
|
|
14069
14189
|
const emitter = replicatedRecordEmitter;
|
|
14070
14190
|
const { SUBSCRIPTION_ACCOUNT_META_STORE_KEY, deriveSubscriptionAccountMetaRecordKey, buildSubscriptionAccountMetaData, buildSubscriptionAccountMetaTombstoneData, } = await import('../core/SubscriptionAccountMetaReplicatedStore.js');
|
|
14191
|
+
// Every quota change re-projects an account, so one row per op and outcome per ten minutes. No account ids.
|
|
14192
|
+
const followMeEvidence = (op, outcome) => {
|
|
14193
|
+
const failed = outcome === 'error' || outcome === 'unconfirmed' || outcome.startsWith('dropped:');
|
|
14194
|
+
featureEvidence.recordAtMostEvery('multiMachine.accountFollowMe', `${op}:${outcome}`, 600_000, {
|
|
14195
|
+
kind: outcome === 'emitted' ? 'fired' : failed ? 'error' : 'held',
|
|
14196
|
+
reason: `account-meta-${op}:${outcome}`,
|
|
14197
|
+
context: { op, outcome },
|
|
14198
|
+
});
|
|
14199
|
+
};
|
|
14071
14200
|
subscriptionPool.setMetaReplicationEmitter({
|
|
14072
|
-
emitPut: (acct) =>
|
|
14073
|
-
|
|
14201
|
+
emitPut: (acct) => {
|
|
14202
|
+
const projected = emitter.emit(SUBSCRIPTION_ACCOUNT_META_STORE_KEY, deriveSubscriptionAccountMetaRecordKey(acct.id), (hlc, origin, observed) => buildSubscriptionAccountMetaData({ account: acct, hlc, origin, observed }));
|
|
14203
|
+
followMeEvidence('put', projected.outcome);
|
|
14204
|
+
return projected;
|
|
14205
|
+
},
|
|
14206
|
+
emitDelete: (accountId, deletedAt) => {
|
|
14207
|
+
const projected = emitter.emit(SUBSCRIPTION_ACCOUNT_META_STORE_KEY, deriveSubscriptionAccountMetaRecordKey(accountId), (hlc, origin, observed) => buildSubscriptionAccountMetaTombstoneData({ accountId, hlc, origin, deletedAt, observed }));
|
|
14208
|
+
followMeEvidence('delete', projected.outcome);
|
|
14209
|
+
return projected;
|
|
14210
|
+
},
|
|
14074
14211
|
});
|
|
14075
14212
|
}
|
|
14076
14213
|
// POOL-AWARE QUOTA THROTTLE wiring (docs/specs/POOL-AWARE-QUOTA-THROTTLE-SPEC.md):
|
|
@@ -16350,6 +16487,23 @@ export async function startServer(options) {
|
|
|
16350
16487
|
externalBlockSweepMs: aoftRawCfg.externalBlockSweepMs,
|
|
16351
16488
|
holdsLease: () => (leaseCoordinatorRef ? leaseCoordinatorRef.holdsLease() : true),
|
|
16352
16489
|
});
|
|
16490
|
+
// The aoft.* events have no other reader: keep them, with no message text (ids and reason codes only).
|
|
16491
|
+
for (const [event, kind] of [
|
|
16492
|
+
['aoft.would-suppress', 'fired'], ['aoft.suppressed', 'fired'],
|
|
16493
|
+
['aoft.would-reroute-terminal', 'fired'], ['aoft.terminal-rerouted', 'fired'],
|
|
16494
|
+
['aoft.would-deadletter-external', 'fired'], ['aoft.deadlettered-external', 'fired'],
|
|
16495
|
+
['aoft.external-block-recorded-internal', 'held'],
|
|
16496
|
+
['aoft.graveyard-reconciled', 'fired'],
|
|
16497
|
+
['aoft.beacon-id-leak', 'error'],
|
|
16498
|
+
]) {
|
|
16499
|
+
promiseBeacon.on(event, (e) => {
|
|
16500
|
+
featureEvidence.record('commitments.agentOwnedFollowthrough', {
|
|
16501
|
+
kind,
|
|
16502
|
+
reason: event.replace('aoft.', '') + (e?.reason ? `: ${e.reason}` : ''),
|
|
16503
|
+
context: { commitmentId: e?.id ?? null, topicId: e?.topicId ?? null, sendKind: e?.kind ?? null, dryRun: event.includes('would-') || e?.dryRun === true, closed: e?.closed ?? null, wouldClose: e?.wouldClose ?? null, leakedTerms: Array.isArray(e?.terms) ? e.terms.length : null },
|
|
16504
|
+
});
|
|
16505
|
+
});
|
|
16506
|
+
}
|
|
16353
16507
|
promiseBeacon.start();
|
|
16354
16508
|
globalThis.__instarPromiseBeacon = promiseBeacon;
|
|
16355
16509
|
// ── AutonomousProgressHeartbeat ──────────────────────────────────
|
|
@@ -16467,6 +16621,30 @@ export async function startServer(options) {
|
|
|
16467
16621
|
maxHeartbeatsPerRun: ahRawCfg.maxHeartbeatsPerRun,
|
|
16468
16622
|
recentOutputChangeWindowMs: ahRawCfg.recentOutputChangeWindowMs,
|
|
16469
16623
|
});
|
|
16624
|
+
// The focus line is a session's own words: never in a row. Suppressions run every tick, so only a change of reason per topic writes one.
|
|
16625
|
+
const ahLastHold = new Map();
|
|
16626
|
+
autonomousHeartbeat.on('would-emit', (e) => {
|
|
16627
|
+
ahLastHold.delete(e.topicId);
|
|
16628
|
+
featureEvidence.record('monitoring.autonomousHeartbeat', { kind: 'fired', reason: 'would emit (dry run)', context: { topicId: e.topicId, minutesSilent: e.minutesSilent, dryRun: true } });
|
|
16629
|
+
});
|
|
16630
|
+
autonomousHeartbeat.on('emitted', (e) => {
|
|
16631
|
+
ahLastHold.delete(e.topicId);
|
|
16632
|
+
featureEvidence.record('monitoring.autonomousHeartbeat', { kind: 'fired', reason: 'emitted', context: { topicId: e.topicId, minutesSilent: e.minutesSilent, dryRun: false } });
|
|
16633
|
+
});
|
|
16634
|
+
autonomousHeartbeat.on('send-error', (e) => {
|
|
16635
|
+
featureEvidence.record('monitoring.autonomousHeartbeat', { kind: 'error', reason: 'send failed', context: { topicId: e.topicId, errorName: e.err instanceof Error ? e.err.name : 'unknown' } });
|
|
16636
|
+
});
|
|
16637
|
+
autonomousHeartbeat.on('tick-error', (err) => {
|
|
16638
|
+
featureEvidence.recordAtMostEvery('monitoring.autonomousHeartbeat', 'tick-error', 60 * 60 * 1000, { kind: 'error', reason: 'tick failed', context: { errorName: err instanceof Error ? err.name : 'unknown' } });
|
|
16639
|
+
});
|
|
16640
|
+
autonomousHeartbeat.on('suppressed', (e) => {
|
|
16641
|
+
if (ahLastHold.get(e.topicId) === e.reason)
|
|
16642
|
+
return;
|
|
16643
|
+
if (ahLastHold.size >= 256)
|
|
16644
|
+
ahLastHold.clear();
|
|
16645
|
+
ahLastHold.set(e.topicId, e.reason);
|
|
16646
|
+
featureEvidence.record('monitoring.autonomousHeartbeat', { kind: 'held', reason: `suppressed: ${e.reason}`, context: { topicId: e.topicId } });
|
|
16647
|
+
});
|
|
16470
16648
|
autonomousHeartbeat.start();
|
|
16471
16649
|
globalThis.__instarAutonomousHeartbeat = autonomousHeartbeat;
|
|
16472
16650
|
guardRegistry.register('monitoring.autonomousHeartbeat.enabled', () => autonomousHeartbeat.guardStatus());
|
|
@@ -19599,6 +19777,17 @@ export async function startServer(options) {
|
|
|
19599
19777
|
});
|
|
19600
19778
|
if (featureRegistryReady) {
|
|
19601
19779
|
featureRegistry.bootstrap(config);
|
|
19780
|
+
// docs/specs/recommended-services.md: old declines carry over before any list is built.
|
|
19781
|
+
if (_recommendedServicesLedger) {
|
|
19782
|
+
try {
|
|
19783
|
+
const { importLegacyDeclines } = await import('../recommended/legacyDeclines.js');
|
|
19784
|
+
importLegacyDeclines(_recommendedServicesLedger, (id) => featureRegistry.getState(id, 'default')?.discoveryState ?? null);
|
|
19785
|
+
}
|
|
19786
|
+
catch (err) {
|
|
19787
|
+
// @silent-fallback-ok: reported; idempotent, so it retries at next boot, and optional work never blocks startup
|
|
19788
|
+
console.warn(` [recommended-services] old declines could not be imported yet: ${err instanceof Error ? err.message : String(err)}`);
|
|
19789
|
+
}
|
|
19790
|
+
}
|
|
19602
19791
|
}
|
|
19603
19792
|
{
|
|
19604
19793
|
const summaries = featureRegistry.getSummaries();
|
|
@@ -20474,6 +20663,102 @@ export async function startServer(options) {
|
|
|
20474
20663
|
_swapAntiThrashEngine = null;
|
|
20475
20664
|
_swapWorkGate = null;
|
|
20476
20665
|
}
|
|
20666
|
+
// A dead sign-in key on a key-only agent: confirmed, told, recovered (spec cloud-key-internal-calls).
|
|
20667
|
+
// Wired here, outside the subscription pool block, because these agents may have no pool.
|
|
20668
|
+
{
|
|
20669
|
+
const { ClaudeKeyHealth, claudeKeyFingerprint, setActiveClaudeKeyHealth } = await import('../core/ClaudeKeyHealth.js');
|
|
20670
|
+
const { buildClaudeKeyProbe } = await import('../core/claudeKeyProbe.js');
|
|
20671
|
+
const { configuredClaudeOauthKey, setClaudeCallOutcomeListener } = await import('../core/claudeChildAuth.js');
|
|
20672
|
+
const keyHealthOn = () => liveConfig.get('sessions.claudeKeyHealth.enabled', true) !== false;
|
|
20673
|
+
const sendToSlackKey = async (routingKey, text) => {
|
|
20674
|
+
const [channelId, threadTs] = routingKey.split(':');
|
|
20675
|
+
await _slackAdapter.sendToChannel(channelId, text, threadTs ? { thread_ts: threadTs } : undefined);
|
|
20676
|
+
};
|
|
20677
|
+
// The disk read covers a topic bound after this server booted, as SessionRefresh does.
|
|
20678
|
+
const topicForSession = (name) => telegram?.getTopicForSession(name) ?? telegram?.resolveTopicForSessionFromDisk?.(name) ?? null;
|
|
20679
|
+
const claudeKeyHealth = new ClaudeKeyHealth({
|
|
20680
|
+
stateFile: path.join(config.stateDir, 'state', 'claude-key-health.json'),
|
|
20681
|
+
currentKey: () => (keyHealthOn() ? configuredClaudeOauthKey() : undefined),
|
|
20682
|
+
currentRawKey: () => config.sessions.anthropicApiKey,
|
|
20683
|
+
readKeyFromDisk: () => (keyHealthOn() ? readConfiguredAnthropicKey(config.stateDir) : undefined),
|
|
20684
|
+
applyKey: (key) => {
|
|
20685
|
+
config.sessions.anthropicApiKey = key ?? undefined;
|
|
20686
|
+
sessionManager.setAnthropicKey(key);
|
|
20687
|
+
},
|
|
20688
|
+
probe: buildClaudeKeyProbe({
|
|
20689
|
+
claudePath: () => resolveFrameworkBinaryPath({
|
|
20690
|
+
framework: 'claude-code',
|
|
20691
|
+
frameworkBinaryPaths: config.sessions.frameworkBinaryPaths,
|
|
20692
|
+
claudePath: config.sessions.claudePath,
|
|
20693
|
+
configuredFramework: config.sessions.framework,
|
|
20694
|
+
}) ?? detectClaudePath(),
|
|
20695
|
+
baseUrl: () => config.sessions.anthropicBaseUrl,
|
|
20696
|
+
}),
|
|
20697
|
+
// Fixed server text straight to the adapters: the model is what is down, and `notify` returns
|
|
20698
|
+
// nothing, so it can't say whether anyone was told.
|
|
20699
|
+
notifyOperator: async (text) => {
|
|
20700
|
+
let delivered = false;
|
|
20701
|
+
const hubTopicId = state.get('agent-attention-topic') ?? 0;
|
|
20702
|
+
if (telegram && hubTopicId) {
|
|
20703
|
+
try {
|
|
20704
|
+
await telegram.sendToTopic(hubTopicId, text);
|
|
20705
|
+
delivered = true;
|
|
20706
|
+
}
|
|
20707
|
+
catch (err) { /* @silent-fallback-ok: `delivered` stays false, which drives the retry and its capped report */
|
|
20708
|
+
console.warn(`[ClaudeKeyHealth] Telegram notice failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
20709
|
+
}
|
|
20710
|
+
}
|
|
20711
|
+
const attentionChannel = state.get('slack-attention-channel');
|
|
20712
|
+
if (_slackAdapter && attentionChannel) {
|
|
20713
|
+
try {
|
|
20714
|
+
await _slackAdapter.sendToChannel(attentionChannel, text);
|
|
20715
|
+
delivered = true;
|
|
20716
|
+
}
|
|
20717
|
+
catch (err) { /* @silent-fallback-ok: `delivered` stays false, which drives the retry and its capped report */
|
|
20718
|
+
console.warn(`[ClaudeKeyHealth] Slack notice failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
20719
|
+
}
|
|
20720
|
+
}
|
|
20721
|
+
return delivered;
|
|
20722
|
+
},
|
|
20723
|
+
notifyPerson: async (sessionName, text) => {
|
|
20724
|
+
const topicId = topicForSession(sessionName);
|
|
20725
|
+
if (topicId !== null) {
|
|
20726
|
+
await telegram.sendToTopic(topicId, text);
|
|
20727
|
+
return true;
|
|
20728
|
+
}
|
|
20729
|
+
const routingKey = _slackAdapter?.getChannelForSession(sessionName) ?? null;
|
|
20730
|
+
if (routingKey !== null) {
|
|
20731
|
+
await sendToSlackKey(routingKey, text);
|
|
20732
|
+
return true;
|
|
20733
|
+
}
|
|
20734
|
+
return false;
|
|
20735
|
+
},
|
|
20736
|
+
listStuckSessions: async () => (await sessionManager.listSessionsAtLoginScreen()).filter((name) => topicForSession(name) !== null || (_slackAdapter?.getChannelForSession(name) ?? null) !== null),
|
|
20737
|
+
sessionLaunchFingerprint: (tmuxSession) => {
|
|
20738
|
+
const launched = sessionManager.sessionLaunchKey(tmuxSession);
|
|
20739
|
+
return launched ? claudeKeyFingerprint(launched) : null;
|
|
20740
|
+
},
|
|
20741
|
+
refresh: async (sessionName, prompt) => {
|
|
20742
|
+
if (!_sessionRefresh)
|
|
20743
|
+
return { ok: false, reason: 'session refresh not available' };
|
|
20744
|
+
const r = await _sessionRefresh.refreshSession({ sessionName, followUpPrompt: prompt, reason: 'claude-key-restored' });
|
|
20745
|
+
return r.ok ? { ok: true, newSessionName: r.newSessionName } : { ok: false, reason: r.code };
|
|
20746
|
+
},
|
|
20747
|
+
clearLoginReports: () => sessionManager.clearInteractiveLoginReports(),
|
|
20748
|
+
report: ({ reason, impact }) => DegradationReporter.getInstance().report({
|
|
20749
|
+
feature: 'ClaudeKeyHealth',
|
|
20750
|
+
primary: 'the configured Claude sign-in key authenticates every model call',
|
|
20751
|
+
fallback: 'the operator is told and stuck conversations wait for a working key',
|
|
20752
|
+
reason,
|
|
20753
|
+
impact,
|
|
20754
|
+
}),
|
|
20755
|
+
logger: { log: (m) => console.log(m), warn: (m) => console.warn(m) },
|
|
20756
|
+
});
|
|
20757
|
+
setActiveClaudeKeyHealth(claudeKeyHealth);
|
|
20758
|
+
setClaudeCallOutcomeListener((outcome) => claudeKeyHealth.noteCallOutcome(outcome));
|
|
20759
|
+
sessionManager.prependInteractiveLoginExpiredSink((signal) => claudeKeyHealth.handle(signal));
|
|
20760
|
+
void claudeKeyHealth.boot().catch((err) => console.warn(`[ClaudeKeyHealth] boot failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
20761
|
+
}
|
|
20477
20762
|
// SessionRefresh — agent-initiated session respawn. Requires a Telegram
|
|
20478
20763
|
// adapter (v1 scope: Telegram-bound sessions only). The respawner closure
|
|
20479
20764
|
// captures `topicMemory` by reference, so even if topicMemory is wired up
|
|
@@ -22885,7 +23170,22 @@ export async function startServer(options) {
|
|
|
22885
23170
|
};
|
|
22886
23171
|
_refreshPoolHeartbeat = refreshPool;
|
|
22887
23172
|
refreshPool();
|
|
22888
|
-
const
|
|
23173
|
+
const readinessMod = await import('../core/poolReadiness.js');
|
|
23174
|
+
const durableOwnershipMod = await import('../core/durableOwnershipActivation.js');
|
|
23175
|
+
const poolReadinessDeps = {
|
|
23176
|
+
peerIds: () => Object.entries(coordinator.managers.identityManager.loadRegistry().machines ?? {})
|
|
23177
|
+
.filter(([id, entry]) => id !== poolSelfId && !entry.revokedAt)
|
|
23178
|
+
.map(([id]) => id),
|
|
23179
|
+
capacity: (id) => machinePoolRegistry.getCapacityForReport(id),
|
|
23180
|
+
ownChannels: () => selfServesChannels(),
|
|
23181
|
+
durableOwnership: () => durableOwnershipMod.shouldActivateDurableOwnership(config, resolveDevAgentGate),
|
|
23182
|
+
duplicateCheck: () => _duplicateReconciler?.status() ?? null,
|
|
23183
|
+
takeover: () => _takeoverReadiness,
|
|
23184
|
+
};
|
|
23185
|
+
readinessMod.setActivePoolReadiness(poolReadinessDeps);
|
|
23186
|
+
const poolReadinessLog = new readinessMod.PoolReadinessLog(poolReadinessDeps, path.join(config.stateDir, '..', 'logs', 'pool-readiness.jsonl'));
|
|
23187
|
+
const poolBeat = () => { refreshPool(); poolReadinessLog.tick(); };
|
|
23188
|
+
const poolTimer = setInterval(poolBeat, 30_000);
|
|
22889
23189
|
if (typeof poolTimer.unref === 'function')
|
|
22890
23190
|
poolTimer.unref();
|
|
22891
23191
|
// Boot-time pool-flag-coherence check (multi-machine-replicated-store-
|
|
@@ -23415,6 +23715,7 @@ export async function startServer(options) {
|
|
|
23415
23715
|
// root at already-paired peers remains an explicit operator/PIN step;
|
|
23416
23716
|
// the bearer recovery path can never become the first root writer.
|
|
23417
23717
|
const escrow = machineRecoveryKey.ensure(meshSelfId, own.recoveryEpoch ?? 0, own.recoveryPublicKey);
|
|
23718
|
+
_recoveryEscrowEvidence = { minted: !!escrow, recoveryEpoch: own.recoveryEpoch ?? 0, hadRoot: !!own.recoveryPublicKey };
|
|
23418
23719
|
if (own.recoveryPublicKey && !escrow) {
|
|
23419
23720
|
try {
|
|
23420
23721
|
_meshAttentionRaise?.({
|
|
@@ -24121,6 +24422,43 @@ export async function startServer(options) {
|
|
|
24121
24422
|
return []; /* @silent-fallback-ok — no planner → no overload moves (today's behavior) */
|
|
24122
24423
|
}
|
|
24123
24424
|
},
|
|
24425
|
+
// A shed move goes through the owner-side drain: it closes the session and hands
|
|
24426
|
+
// over custody. One at a time; the slot is held until the runner settles, so a
|
|
24427
|
+
// hung drain blocks further moves rather than stacking them.
|
|
24428
|
+
drainMove: (mv, epoch) => {
|
|
24429
|
+
const planner = getActiveOverloadShedPlanner();
|
|
24430
|
+
if (!planner)
|
|
24431
|
+
return;
|
|
24432
|
+
if (_shedDrainInFlight)
|
|
24433
|
+
return;
|
|
24434
|
+
if (!_drainRunner) {
|
|
24435
|
+
planner.noteMoveOutcome(mv.sessionKey, { status: 'refused-no-drain-runner' });
|
|
24436
|
+
return;
|
|
24437
|
+
}
|
|
24438
|
+
const target = machinePoolRegistry?.getCapacity(mv.target);
|
|
24439
|
+
if (!target || target.liveness?.state !== 'live' || target.loadVerdict !== 'ok' || target.loadReport?.acceptingWork === false) {
|
|
24440
|
+
planner.noteMoveOutcome(mv.sessionKey, { status: 'refused-target-changed' });
|
|
24441
|
+
return;
|
|
24442
|
+
}
|
|
24443
|
+
_shedDrainInFlight = true;
|
|
24444
|
+
const startedAt = Date.now();
|
|
24445
|
+
_shedDrainTopics.add(mv.sessionKey);
|
|
24446
|
+
void _drainRunner.run({ sessionKey: mv.sessionKey, target: mv.target, senderObservedEpoch: epoch, onNotQuiet: 'abort' })
|
|
24447
|
+
.then((o) => {
|
|
24448
|
+
if (o.status === 'drained' || o.status === 'drained-interrupted') {
|
|
24449
|
+
const topicNum = Number(mv.sessionKey);
|
|
24450
|
+
if (Number.isFinite(topicNum)) {
|
|
24451
|
+
try {
|
|
24452
|
+
getMoveAftercare()?.(mv.target, topicNum);
|
|
24453
|
+
}
|
|
24454
|
+
catch { /* @silent-fallback-ok — the kick has bounded retries; the target can still fetch */ }
|
|
24455
|
+
}
|
|
24456
|
+
}
|
|
24457
|
+
planner.noteMoveOutcome(mv.sessionKey, { status: o.status, claimLanded: o.claimLanded, durationMs: Date.now() - startedAt, ...(o.detail ? { detail: o.detail } : {}) });
|
|
24458
|
+
})
|
|
24459
|
+
.catch((err) => { planner.noteMoveOutcome(mv.sessionKey, { status: 'refused-drain-threw', detail: err instanceof Error ? err.message : String(err) }); })
|
|
24460
|
+
.finally(() => { _shedDrainInFlight = false; _shedDrainTopics.delete(mv.sessionKey); });
|
|
24461
|
+
},
|
|
24124
24462
|
// Live only when overload shed is enabled AND out of dry-run: driving unpinned
|
|
24125
24463
|
// transfers (claim / abort past the deadline) is real authority over every
|
|
24126
24464
|
// unpinned in-flight transfer, so the soft dry-run lever must hold it too.
|
|
@@ -24185,6 +24523,7 @@ export async function startServer(options) {
|
|
|
24185
24523
|
enabled: resolveDevAgentGate(c?.enabled, config),
|
|
24186
24524
|
dryRun: c?.dryRun ?? dflt.dryRun,
|
|
24187
24525
|
sourceAfterMs: c?.sourceAfterMs ?? dflt.sourceAfterMs,
|
|
24526
|
+
topicCooldownMs: c?.topicCooldownMs ?? dflt.topicCooldownMs,
|
|
24188
24527
|
maxMovesPerHour: c?.maxMovesPerHour ?? dflt.maxMovesPerHour,
|
|
24189
24528
|
recentShedMs: c?.recentShedMs ?? dflt.recentShedMs,
|
|
24190
24529
|
};
|
|
@@ -24198,6 +24537,39 @@ export async function startServer(options) {
|
|
|
24198
24537
|
return true; /* @silent-fallback-ok — an unreadable pin view treats the topic as pinned (never moved) */
|
|
24199
24538
|
}
|
|
24200
24539
|
};
|
|
24540
|
+
const shedProofTopics = () => new Set(config.multiMachine?.sessionPool?.rebalanceProofTopics ?? []);
|
|
24541
|
+
// Topics with a running session here, with when the conversation last moved.
|
|
24542
|
+
// One cached listing; the work-state reads stay off the planner's sync tick.
|
|
24543
|
+
const quietScanner = new QuietTopicScanner({
|
|
24544
|
+
runningTopicSessions: () => {
|
|
24545
|
+
if (!telegram)
|
|
24546
|
+
return [];
|
|
24547
|
+
const out = [];
|
|
24548
|
+
for (const s of sessionManager.getCachedRunningSessions().sessions) {
|
|
24549
|
+
const topic = telegram.getTopicForSession(s.tmuxSession);
|
|
24550
|
+
if (topic === null || topic === undefined)
|
|
24551
|
+
continue;
|
|
24552
|
+
const last = telegram.getTopicHistory(topic, 1)[0];
|
|
24553
|
+
const at = last ? Date.parse(last.timestamp) : NaN;
|
|
24554
|
+
out.push({ sessionKey: String(topic), tmuxSession: s.tmuxSession, lastActivityAt: Number.isFinite(at) ? at : null });
|
|
24555
|
+
}
|
|
24556
|
+
return out;
|
|
24557
|
+
},
|
|
24558
|
+
workState: (tmux) => sessionManager.checkSessionWorkState(tmux),
|
|
24559
|
+
movable: (key) => {
|
|
24560
|
+
const r = ownReg.read(key);
|
|
24561
|
+
if (r?.status !== 'active' || r.ownerMachineId !== _meshSelfId)
|
|
24562
|
+
return false;
|
|
24563
|
+
if (shedPinned(key) || shedProofTopics().has(Number(key)))
|
|
24564
|
+
return false;
|
|
24565
|
+
try {
|
|
24566
|
+
return !autoSessionsMod.listAutonomousJobs(config.stateDir).find((j) => j.topic === key && j.active && !j.paused);
|
|
24567
|
+
}
|
|
24568
|
+
catch {
|
|
24569
|
+
return false; /* @silent-fallback-ok: unreadable run registry: treat the topic as not movable */
|
|
24570
|
+
}
|
|
24571
|
+
},
|
|
24572
|
+
});
|
|
24201
24573
|
const planner = new shedMod.OverloadShedPlanner({
|
|
24202
24574
|
config: shedCfg,
|
|
24203
24575
|
selfMachineId: () => _meshSelfId,
|
|
@@ -24205,7 +24577,16 @@ export async function startServer(options) {
|
|
|
24205
24577
|
capacities: () => machinePoolRegistry?.getCapacities() ?? [],
|
|
24206
24578
|
ownedTopics: () => ownReg.all()
|
|
24207
24579
|
.filter((r) => r.status === 'active' && r.ownerMachineId === _meshSelfId)
|
|
24208
|
-
.map((r) => ({ sessionKey: r.sessionKey, pinned: shedPinned(r.sessionKey) })),
|
|
24580
|
+
.map((r) => ({ sessionKey: r.sessionKey, pinned: shedPinned(r.sessionKey), lastMovedAt: r.timestamp })),
|
|
24581
|
+
poolStage: () => liveConfig.get('multiMachine.sessionPool.stage', 'dark'),
|
|
24582
|
+
proofFresh: () => {
|
|
24583
|
+
if (!_rebalanceProofStore)
|
|
24584
|
+
return false;
|
|
24585
|
+
return rebalanceProofState(_rebalanceProofStore, Date.now()).fresh;
|
|
24586
|
+
},
|
|
24587
|
+
quietTopics: () => quietScanner.current(),
|
|
24588
|
+
moveActuatorLive: () => resolveDevAgentGate(ws13Cfg().ws13Reconcile, config) && ws13Cfg().ws13DryRun === false,
|
|
24589
|
+
isProofTopic: (key) => shedProofTopics().has(Number(key)),
|
|
24209
24590
|
ownerOf: (key) => ownReg.read(key)?.ownerMachineId,
|
|
24210
24591
|
statusOf: (key) => {
|
|
24211
24592
|
const r = ownReg.read(key);
|
|
@@ -24229,7 +24610,81 @@ export async function startServer(options) {
|
|
|
24229
24610
|
log: (line) => console.log(pc.yellow(` [overload-shed] ${line}`)),
|
|
24230
24611
|
});
|
|
24231
24612
|
shedMod.setActiveOverloadShedPlanner(planner);
|
|
24613
|
+
// The rebalance proof: drives this planner's real path, judged from outside it.
|
|
24614
|
+
const proofMarker = path.join(config.stateDir, 'rebalance-proof-in-flight');
|
|
24615
|
+
setActiveRebalanceProof(new RebalanceProofRunner({
|
|
24616
|
+
selfMachineId: () => _meshSelfId,
|
|
24617
|
+
isProofTopic: (t) => shedProofTopics().has(t),
|
|
24618
|
+
stage: () => liveConfig.get('multiMachine.sessionPool.stage', 'dark'),
|
|
24619
|
+
stageAllowsProof: () => {
|
|
24620
|
+
const st = liveConfig.get('multiMachine.sessionPool.stage', 'dark');
|
|
24621
|
+
return st === 'live-transfer' || st === 'rebalance';
|
|
24622
|
+
},
|
|
24623
|
+
readRecord: (t) => ownReg.read(String(t)),
|
|
24624
|
+
hasLocalSession: (t) => {
|
|
24625
|
+
const tmux = telegram?.getSessionForTopic(t);
|
|
24626
|
+
return !!tmux && sessionManager.isSessionAlive(tmux);
|
|
24627
|
+
},
|
|
24628
|
+
ensureIdleSession: async (t, timeoutMs) => {
|
|
24629
|
+
if (!telegram)
|
|
24630
|
+
return false;
|
|
24631
|
+
const live = () => { const m = telegram.getSessionForTopic(t); return m && sessionManager.isSessionAlive(m) ? m : null; };
|
|
24632
|
+
if (!live()) {
|
|
24633
|
+
const name = await spawnSessionForTopic(sessionManager, telegram, `proof-${t}`, t, proofSpawnBrief());
|
|
24634
|
+
telegram.registerTopicSession(t, name, `proof-${t}`);
|
|
24635
|
+
}
|
|
24636
|
+
const deadline = Date.now() + timeoutMs;
|
|
24637
|
+
while (Date.now() < deadline) {
|
|
24638
|
+
const tmux = live();
|
|
24639
|
+
if (tmux && (await sessionManager.checkSessionWorkState(tmux)) === 'idle')
|
|
24640
|
+
return true;
|
|
24641
|
+
await new Promise((r) => setTimeout(r, 5_000));
|
|
24642
|
+
}
|
|
24643
|
+
return false;
|
|
24644
|
+
},
|
|
24645
|
+
move: (t, to) => planner.proofMove(String(t), to),
|
|
24646
|
+
sendProbe: async (t, text, messageId) => {
|
|
24647
|
+
if (!_sessionRouter)
|
|
24648
|
+
return 'no-router';
|
|
24649
|
+
const o = await _sessionRouter.route({ sessionKey: String(t), messageId, payload: text, senderEnvelope: null });
|
|
24650
|
+
return o.action;
|
|
24651
|
+
},
|
|
24652
|
+
readHistory: async (t) => {
|
|
24653
|
+
const r = await fetch(`http://127.0.0.1:${config.port}/telegram/topics/${t}/messages?scope=pool&limit=50`, {
|
|
24654
|
+
headers: { Authorization: `Bearer ${config.authToken}`, 'X-Instar-AgentId': config.projectName },
|
|
24655
|
+
});
|
|
24656
|
+
if (!r.ok)
|
|
24657
|
+
throw new Error(`history ${r.status}`);
|
|
24658
|
+
const j = await r.json();
|
|
24659
|
+
return { rows: j.messages ?? [], failed: (j.pool?.failed ?? []).map((f) => (typeof f === 'string' ? f : f.machineId ?? '')) };
|
|
24660
|
+
},
|
|
24661
|
+
record: (result, evidenceRef) => {
|
|
24662
|
+
_rebalanceProofStore?.recordResult(3, result, _sessionPoolBuildIdentity?.() ?? 'unknown', evidenceRef);
|
|
24663
|
+
},
|
|
24664
|
+
writeEvidence: (ev) => {
|
|
24665
|
+
const dir = path.join(config.stateDir, '..', 'logs', 'rebalance-proof');
|
|
24666
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
24667
|
+
const file = path.join(dir, `${new Date().toISOString().replace(/[:.]/g, '-')}.json`);
|
|
24668
|
+
fs.writeFileSync(file, JSON.stringify(ev, null, 2));
|
|
24669
|
+
return file;
|
|
24670
|
+
},
|
|
24671
|
+
newNonce: () => crypto.randomUUID().replace(/-/g, '').slice(0, 12),
|
|
24672
|
+
markInFlight: (runId) => fs.writeFileSync(proofMarker, runId),
|
|
24673
|
+
readInFlight: () => { try {
|
|
24674
|
+
return fs.readFileSync(proofMarker, 'utf8').trim() || null;
|
|
24675
|
+
}
|
|
24676
|
+
catch {
|
|
24677
|
+
return null; /* @silent-fallback-ok — no marker means no unfinished run */
|
|
24678
|
+
} },
|
|
24679
|
+
clearInFlight: () => { SafeFsExecutor.safeRmSync(proofMarker, { force: true, operation: 'rebalance-proof: run finished' }); },
|
|
24680
|
+
log: (line) => console.log(pc.dim(` [rebalance-proof] ${line}`)),
|
|
24681
|
+
}));
|
|
24232
24682
|
_overloadShedTimer = setInterval(() => {
|
|
24683
|
+
// The scan is cheap to skip: it only matters while this machine is a source.
|
|
24684
|
+
if (planner.status().isSource === true)
|
|
24685
|
+
void quietScanner.refresh();
|
|
24686
|
+
else
|
|
24687
|
+
quietScanner.clear();
|
|
24233
24688
|
try {
|
|
24234
24689
|
planner.tick();
|
|
24235
24690
|
}
|
|
@@ -24619,6 +25074,9 @@ export async function startServer(options) {
|
|
|
24619
25074
|
// release replicates exactly like the user-move release does. A lost CAS
|
|
24620
25075
|
// (peer advanced the epoch first) is a no-op here — we never retry/force.
|
|
24621
25076
|
emitPlacement(sk, r, 'released', prevOwner);
|
|
25077
|
+
featureEvidence.record('multiMachine.ownershipFollowsLiveWork', r.ok
|
|
25078
|
+
? { kind: 'fired', reason: 'release-on-complete: ownership released', context: { topicId: sk, part: 'release-on-complete', prevOwner: prevOwner ?? null } }
|
|
25079
|
+
: { kind: 'error', reason: 'release-on-complete: compare-and-set refused', context: { topicId: sk, part: 'release-on-complete', prevOwner: prevOwner ?? null } });
|
|
24622
25080
|
}
|
|
24623
25081
|
catch {
|
|
24624
25082
|
// @silent-fallback-ok — release-on-complete is best-effort housekeeping
|
|
@@ -25028,9 +25486,16 @@ export async function startServer(options) {
|
|
|
25028
25486
|
const r = ownReg.cas(action, c);
|
|
25029
25487
|
// Journal pairing (§3.3): the drain's transfer/abort/claim CASes
|
|
25030
25488
|
// record placement history like every other CAS site.
|
|
25031
|
-
emitPlacement(c.sessionKey, r, 'user-move', prev);
|
|
25489
|
+
emitPlacement(c.sessionKey, r, _shedDrainTopics.has(c.sessionKey) ? 'reconcile' : 'user-move', prev);
|
|
25032
25490
|
return r;
|
|
25033
25491
|
},
|
|
25492
|
+
sessionIdleNow: async (sk) => {
|
|
25493
|
+
const topicNum = Number(sk);
|
|
25494
|
+
const tmux = Number.isFinite(topicNum) ? telegram?.getSessionForTopic(topicNum) : null;
|
|
25495
|
+
if (!tmux || !sessionManager.isSessionAlive(tmux))
|
|
25496
|
+
return true; // nothing local to disturb
|
|
25497
|
+
return (await sessionManager.checkSessionWorkState(tmux)) === 'idle';
|
|
25498
|
+
},
|
|
25034
25499
|
suspendAutonomousRun: (topic, target) => autoMod.suspendAutonomousTopicForMove(config.stateDir, topic, target, coherenceJournal ?? undefined),
|
|
25035
25500
|
sessionQuiet: (sk) => {
|
|
25036
25501
|
const topicNum = Number(sk);
|
|
@@ -27921,6 +28386,11 @@ export async function startServer(options) {
|
|
|
27921
28386
|
}
|
|
27922
28387
|
runMachineCoherenceEffects?.(effects, { telegram: () => tg ?? null });
|
|
27923
28388
|
};
|
|
28389
|
+
const meshEvidence = (kind, reason) => {
|
|
28390
|
+
featureEvidence.record('monitoring.meshCoherenceLiveCheck', { kind, reason, context: { uptimeSec: Math.round(process.uptime()), emitCap: config.monitoring?.meshCoherenceLiveCheck?.emitCap ?? null } });
|
|
28391
|
+
};
|
|
28392
|
+
const meshFired = (code) => { meshEvidence('fired', `divergence:${code}`); return true; };
|
|
28393
|
+
const meshHeld = (code) => meshEvidence('held', `emit-cap:${code}`);
|
|
27924
28394
|
const peerPresenceTick = () => {
|
|
27925
28395
|
void reconcileIdentityActivation().catch((err) => {
|
|
27926
28396
|
console.warn(`[identity-recovery] periodic activation reconciliation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -27960,8 +28430,10 @@ export async function startServer(options) {
|
|
|
27960
28430
|
if (emitCap === undefined || count < emitCap) { // emitCap is READ here
|
|
27961
28431
|
console.log(pc.yellow(` ⚠ mesh-live-coherence [${w.code}]: ${w.message}`));
|
|
27962
28432
|
_meshCoherenceEmitCounts.set(w.code, count + 1);
|
|
27963
|
-
firedThisTick =
|
|
28433
|
+
firedThisTick = meshFired(w.code);
|
|
27964
28434
|
}
|
|
28435
|
+
else
|
|
28436
|
+
meshHeld(w.code);
|
|
27965
28437
|
}
|
|
27966
28438
|
}
|
|
27967
28439
|
recorder?.record({ feature: 'mesh-coherence-live', kind: 'event', outcome: firedThisTick ? 'fired' : 'noop' });
|
|
@@ -27979,6 +28451,8 @@ export async function startServer(options) {
|
|
|
27979
28451
|
_meshCoherenceFailing = true;
|
|
27980
28452
|
}
|
|
27981
28453
|
_meshCoherenceConsecFailures += 1;
|
|
28454
|
+
if (_meshCoherenceConsecFailures === 1)
|
|
28455
|
+
meshEvidence('error', 'live-state-read-failed');
|
|
27982
28456
|
}
|
|
27983
28457
|
}
|
|
27984
28458
|
}
|
|
@@ -28452,6 +28926,30 @@ export async function startServer(options) {
|
|
|
28452
28926
|
bootCommitSha = `package:${startupVersion}`;
|
|
28453
28927
|
}
|
|
28454
28928
|
const currentSessionPoolBuildIdentity = () => bootCommitSha || 'unknown';
|
|
28929
|
+
_sessionPoolBuildIdentity = currentSessionPoolBuildIdentity;
|
|
28930
|
+
// The rebalance proof has its own signed store: the failover rows prove failover, and
|
|
28931
|
+
// 770 of them once sat at stage 3 proving nothing about rebalancing.
|
|
28932
|
+
_rebalanceProofStore = new e2eMod.SessionPoolE2EResultStore({
|
|
28933
|
+
filePath: path.join(config.stateDir, 'session-pool-rebalance-proof.json'),
|
|
28934
|
+
sign: hmac,
|
|
28935
|
+
verifySig: (c, s) => {
|
|
28936
|
+
try {
|
|
28937
|
+
const exp = hmac(c);
|
|
28938
|
+
return s.length === exp.length && crypto.timingSafeEqual(Buffer.from(s), Buffer.from(exp));
|
|
28939
|
+
}
|
|
28940
|
+
catch {
|
|
28941
|
+
return false; /* @silent-fallback-ok: HMAC verify fails closed — a malformed input is an invalid signature, never accepted */
|
|
28942
|
+
}
|
|
28943
|
+
},
|
|
28944
|
+
});
|
|
28945
|
+
setActiveRebalanceProofStore(_rebalanceProofStore);
|
|
28946
|
+
// A failure here must not cost the agent its rollout gate below.
|
|
28947
|
+
try {
|
|
28948
|
+
getActiveRebalanceProof()?.recoverInterrupted();
|
|
28949
|
+
}
|
|
28950
|
+
catch (err) {
|
|
28951
|
+
console.warn('[rebalance-proof] could not record an interrupted run:', err instanceof Error ? err.message : String(err)); /* @silent-fallback-ok (logged): the marker stays and the next boot retries */
|
|
28952
|
+
}
|
|
28455
28953
|
// ONE authoritative stage read for the rollout gate and its proof producer.
|
|
28456
28954
|
// Splitting these previously let the runner stamp every green as stage 0
|
|
28457
28955
|
// while StageAdvancer was already waiting for a green at stage 2.
|
|
@@ -28463,6 +28961,7 @@ export async function startServer(options) {
|
|
|
28463
28961
|
currentCommitSha: currentSessionPoolBuildIdentity,
|
|
28464
28962
|
readStage: readSessionPoolStage,
|
|
28465
28963
|
writeStageConfig: (s) => liveConfig.set(guardMod.STAGE_CONFIG_PATH, s, { stageWriteToken: guardMod.STAGE_WRITE_TOKEN }),
|
|
28964
|
+
rebalanceProof: () => stageMod.rebalanceProofState(_rebalanceProofStore, Date.now()),
|
|
28466
28965
|
audit: (event, detail) => console.log(pc.dim(` [stage-advancer] ${event} ${JSON.stringify(detail)}`)),
|
|
28467
28966
|
});
|
|
28468
28967
|
// ── Promotion activation ────────────────────────────────────────────────
|
|
@@ -28614,7 +29113,7 @@ export async function startServer(options) {
|
|
|
28614
29113
|
currentCommitSha: currentSessionPoolBuildIdentity,
|
|
28615
29114
|
// Credit the proof to the stage that is actually running. The next
|
|
28616
29115
|
// promotion reads this same current-stage index as its prior-stage gate.
|
|
28617
|
-
provenStage: () => stageMod.
|
|
29116
|
+
provenStage: () => stageMod.failoverProvenStage(readSessionPoolStage()),
|
|
28618
29117
|
audit: (event, detail) => console.log(pc.dim(` [failover-runner] ${event} ${JSON.stringify(detail)}`)),
|
|
28619
29118
|
});
|
|
28620
29119
|
if (_sessionPoolFailoverRunnerDriver) {
|
|
@@ -29642,10 +30141,12 @@ export async function startServer(options) {
|
|
|
29642
30141
|
console.warn('[instar] Windows desktop bootstrap diagnostic could not be persisted');
|
|
29643
30142
|
}
|
|
29644
30143
|
}
|
|
29645
|
-
const server = new AgentServer({ config, ecosystemLedger: _ecosystemLedger ?? undefined, singleInstanceLock, agentIdentity: _agentIdentityDeps, terminateSessionAuthority: terminateWithAuthority, subscriptionEmailBinding: credentialLocationLedger, subscriptionEmailBarrier, subscriptionIdentityOracle, sessionManager, llmQueue: sharedLlmQueue, state, scheduler, telegram, telegramOrigin: telegramOriginBoot?.runtime, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, jobAnomalySendAutomationReply: sendAutomationReply, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, cartographerRoots: cartographerRoots ?? undefined, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, subscriptionPool, accountFollowMePeerViews: async () => { const nickById = new Map((_listPoolMachines?.() ?? []).map((m) => [m.machineId, verifiedEntityName(m.machineId, m.nickname) ?? ''])); let peers = (_resolvePeerUrls?.() ?? []).map((p) => ({ machineId: p.machineId, nickname: nickById.get(p.machineId) ?? '', url: p.url })); if (peers.length === 0) {
|
|
30144
|
+
const server = new AgentServer({ config, ecosystemLedger: _ecosystemLedger ?? undefined, recommendedServicesLedger: _recommendedServicesLedger ?? undefined, singleInstanceLock, agentIdentity: _agentIdentityDeps, terminateSessionAuthority: terminateWithAuthority, subscriptionEmailBinding: credentialLocationLedger, subscriptionEmailBarrier, subscriptionIdentityOracle, sessionManager, llmQueue: sharedLlmQueue, state, scheduler, telegram, telegramOrigin: telegramOriginBoot?.runtime, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, jobAnomalySendAutomationReply: sendAutomationReply, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, cartographerRoots: cartographerRoots ?? undefined, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, subscriptionPool, accountFollowMePeerViews: async () => { const nickById = new Map((_listPoolMachines?.() ?? []).map((m) => [m.machineId, verifiedEntityName(m.machineId, m.nickname) ?? ''])); let peers = (_resolvePeerUrls?.() ?? []).map((p) => ({ machineId: p.machineId, nickname: nickById.get(p.machineId) ?? '', url: p.url })); if (peers.length === 0) {
|
|
29646
30145
|
peers = (_listPoolMachines?.() ?? []).filter((m) => m.machineId !== _meshSelfId && !!m.lastKnownUrl).map((m) => ({ machineId: m.machineId, nickname: verifiedEntityName(m.machineId, m.nickname) ?? '', url: m.lastKnownUrl }));
|
|
29647
30146
|
} if (peers.length === 0)
|
|
29648
|
-
return []; const { fetchPeerSubscriptionViews } = await import('../core/fetchPeerSubscriptionViews.js'); return fetchPeerSubscriptionViews({ peers: () => peers, fetchImpl: fetch, authToken: config.authToken ?? '' }); }, quotaPoller, quotaAwareScheduler: _quotaAwareScheduler ?? undefined, proactiveSwapMonitor: _proactiveSwapMonitor ?? undefined, inUseAccountResolver, enrollmentWizard, accountFollowMeRevocation, credentialRepointing, semanticMemory, activitySentinel, rateLimitSentinel, releaseReadinessSentinel: releaseReadinessSentinel ?? undefined, greenPrAutoMerger: greenPrAutoMerger ?? undefined, localVerify: localVerifyService ?? undefined, localVerifyStatus: localVerifyStatus ?? undefined, guardLatchStore: guardLatchStore ?? undefined, agentStopSurfacer: agentStopSurfacer ?? undefined, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, topicProfile: _topicProfileCtx ?? undefined, sessionRefresh: _sessionRefresh ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, meshBindActive: coordinator.managers.identityManager.hasIdentity() && config.multiMachine?.meshTransport?.enabled !== false, localSigningKeyPem, leaseTransport, peerEndpointRecorder, getSelfMeshEndpoints, 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, conversationRegistry, conversationBindAuth, appConversations: _appConversationService ?? undefined, slackInboundDispatch: () => _slackInboundDispatch, conversationFollowThrough, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, conversationStore, threadLog, threadMessageRecorder, warrantsReplyGate, collaborationSurfacer, peerHomebaseRelay, threadResumeMap, topicLinkageHandler: topicLinkageHandler ?? undefined, threadlineRelayClient, pairingInvites: threadlinePairingInvites, getLastRelayEvent: threadlineGetLastRelayEvent, a2aRelayForward: _a2aRelayForwardCtx ?? undefined, threadlineReplyWaiters, threadlineMcpHttp, listenerManager: listenerManager ?? undefined, a2aDeliveryTracker: a2aDeliveryTracker ?? undefined, relayVerdictCounters: threadlineRelayClient ? (() => ({ ...threadlineRelayClient.relayVerdictCounters, expiredMismatchIgnored: a2aDeliveryTracker?.expiredMismatchIgnored ?? 0 })) : undefined, inboundIdLedger: _inboundIdLedger ?? undefined, inboundIdLedgerDaemonDeferred: () => _inboundIdLedgerDaemonDeferred, responseReviewGate, reviewCanaryBattery, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, ropeHealthMonitor, writeAdmission: writeAdmission ?? undefined, getInboundQueue: () => _inboundQueue, getMachineCoherence: () => _machineCoherenceSentinel, getSingleMachineFailoverGap: () => _singleMachineFailoverGap, getMissingLoginSession: () => _missingLoginSession, getSessionPoolFailoverRunner: () => _sessionPoolFailoverRunnerDriver?.status() ?? null, sessionPoolPromotionActivation: _sessionPoolPromotionActivation, meshRpcDispatcher, deliverA2aToMachine: _deliverA2aToMachine ?? undefined, workingSetPullCoordinator, workingSetArtifactManager, orchestratorPoller, commitmentReplicaStore, preferenceReplicaStore, replicatedRecordEmitter, replicatedStoreReconciler, conflictStore, rollbackUnmerge, droppedOriginRegistry, preferencesUnionReader, jevMemoryPicker, forwardCommitmentMutate, sessionOwnershipRegistry, sendDrain: _sendDrain ?? undefined, claimTopicOwnershipOnSpawn: (topicId) => _claimOwnershipForAutonomousSpawn ? _claimOwnershipForAutonomousSpawn(topicId) : 'unwired', topicPinStore: _topicPinStore ?? undefined, topicPinSkewQuarantine: _topicPinSkewQuarantine ?? undefined, topicPinFoldView: _topicPinFoldView ?? undefined, ownershipReconciler: _ownershipReconciler ?? undefined, staleOwnerEngine: _staleOwnerEngine ?? undefined, duplicateReconciler: _duplicateReconciler ?? undefined, ownerDarkLadder: _ownerDarkLadder ?? undefined, spawnAdmission: _spawnAdmission ?? undefined, judgmentProvenance: _judgmentProvenance ?? undefined, leaseHandback: _leaseHandbackCtx ?? 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, recordRopeResult: _recordRopeResult ?? undefined, guardRegistry, listPoolMachines: _listPoolMachines ?? undefined, deliverMandateToMachine: _deliverMandateToMachine ?? undefined, passkeyRevokeOutbox: _passkeyRevokeOutbox ? () => _passkeyRevokeOutbox : undefined, passkeyPeerOnline: _passkeyPeerOnline, passkeyPoolReader: _passkeyPoolReader ? () => _passkeyPoolReader : undefined, passkeyProofBrowser: async (profileDir) => { const { ChromeCdpReloginBrowser } = await import('../core/ChromeCdpReloginBrowser.js'); return new ChromeCdpReloginBrowser({ userDataDir: profileDir, passkeyMode: true, headless: true, launchTimeoutMs: 30_000, operationTimeoutMs: 20_000 }); }, poolLink: _poolLink ?? undefined, poolPollCache: _poolPollCache ?? undefined, sessionPoolE2EResultStore, proxyCoordinator, topicIntentStore, topicIntentArcCheck, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, briefDeps, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper, agentWorktreeReaper, externalHogSentinel, orphanedWorkSentinel, mcpProcessReaper, codexArmSessionSweeper, geminiLoopRunner, sleepController, agentActivityState, reapLog, resumeQueue, resumeDrainer, autonomousLivenessReconciler, enforcedTerminationStatus: () => enforcedTerminationWatchdog?.guardStatus() ?? null, prHandLease: prHandLease ?? undefined, standDownRegistry: _standDownRegistry ?? undefined, standDownAudit: _standDownAudit ?? undefined, operatorStopRecorder: recordOperatorStop, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier, liveTestGate, liveTestGateMode, liveTestRunnerCtx });
|
|
30147
|
+
return []; const { fetchPeerSubscriptionViews } = await import('../core/fetchPeerSubscriptionViews.js'); return fetchPeerSubscriptionViews({ peers: () => peers, fetchImpl: fetch, authToken: config.authToken ?? '' }); }, quotaPoller, quotaAwareScheduler: _quotaAwareScheduler ?? undefined, proactiveSwapMonitor: _proactiveSwapMonitor ?? undefined, inUseAccountResolver, enrollmentWizard, accountFollowMeRevocation, credentialRepointing, semanticMemory, activitySentinel, rateLimitSentinel, releaseReadinessSentinel: releaseReadinessSentinel ?? undefined, greenPrAutoMerger: greenPrAutoMerger ?? undefined, localVerify: localVerifyService ?? undefined, localVerifyStatus: localVerifyStatus ?? undefined, guardLatchStore: guardLatchStore ?? undefined, agentStopSurfacer: agentStopSurfacer ?? undefined, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, topicProfile: _topicProfileCtx ?? undefined, sessionRefresh: _sessionRefresh ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, meshBindActive: coordinator.managers.identityManager.hasIdentity() && config.multiMachine?.meshTransport?.enabled !== false, localSigningKeyPem, leaseTransport, peerEndpointRecorder, getSelfMeshEndpoints, 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, conversationRegistry, conversationBindAuth, appConversations: _appConversationService ?? undefined, slackInboundDispatch: () => _slackInboundDispatch, conversationFollowThrough, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, conversationStore, threadLog, threadMessageRecorder, warrantsReplyGate, collaborationSurfacer, peerHomebaseRelay, threadResumeMap, topicLinkageHandler: topicLinkageHandler ?? undefined, threadlineRelayClient, pairingInvites: threadlinePairingInvites, getLastRelayEvent: threadlineGetLastRelayEvent, a2aRelayForward: _a2aRelayForwardCtx ?? undefined, threadlineReplyWaiters, threadlineMcpHttp, listenerManager: listenerManager ?? undefined, a2aDeliveryTracker: a2aDeliveryTracker ?? undefined, relayVerdictCounters: threadlineRelayClient ? (() => ({ ...threadlineRelayClient.relayVerdictCounters, expiredMismatchIgnored: a2aDeliveryTracker?.expiredMismatchIgnored ?? 0 })) : undefined, inboundIdLedger: _inboundIdLedger ?? undefined, inboundIdLedgerDaemonDeferred: () => _inboundIdLedgerDaemonDeferred, responseReviewGate, reviewCanaryBattery, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, ropeHealthMonitor, writeAdmission: writeAdmission ?? undefined, getInboundQueue: () => _inboundQueue, getMachineCoherence: () => _machineCoherenceSentinel, getSingleMachineFailoverGap: () => _singleMachineFailoverGap, getMissingLoginSession: () => _missingLoginSession, getSessionPoolFailoverRunner: () => _sessionPoolFailoverRunnerDriver?.status() ?? null, sessionPoolPromotionActivation: _sessionPoolPromotionActivation, meshRpcDispatcher, deliverA2aToMachine: _deliverA2aToMachine ?? undefined, workingSetPullCoordinator, workingSetArtifactManager, orchestratorPoller, commitmentReplicaStore, preferenceReplicaStore, replicatedRecordEmitter, replicatedStoreReconciler, conflictStore, rollbackUnmerge, droppedOriginRegistry, preferencesUnionReader, jevMemoryPicker, forwardCommitmentMutate, sessionOwnershipRegistry, sendDrain: _sendDrain ?? undefined, claimTopicOwnershipOnSpawn: (topicId) => _claimOwnershipForAutonomousSpawn ? _claimOwnershipForAutonomousSpawn(topicId) : 'unwired', topicPinStore: _topicPinStore ?? undefined, topicPinSkewQuarantine: _topicPinSkewQuarantine ?? undefined, topicPinFoldView: _topicPinFoldView ?? undefined, ownershipReconciler: _ownershipReconciler ?? undefined, staleOwnerEngine: _staleOwnerEngine ?? undefined, duplicateReconciler: _duplicateReconciler ?? undefined, ownerDarkLadder: _ownerDarkLadder ?? undefined, spawnAdmission: _spawnAdmission ?? undefined, judgmentProvenance: _judgmentProvenance ?? undefined, leaseHandback: _leaseHandbackCtx ?? 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, recordRopeResult: _recordRopeResult ?? undefined, guardRegistry, listPoolMachines: _listPoolMachines ?? undefined, deliverMandateToMachine: _deliverMandateToMachine ?? undefined, passkeyRevokeOutbox: _passkeyRevokeOutbox ? () => _passkeyRevokeOutbox : undefined, passkeyPeerOnline: _passkeyPeerOnline, passkeyPoolReader: _passkeyPoolReader ? () => _passkeyPoolReader : undefined, passkeyProofBrowser: async (profileDir) => { const { ChromeCdpReloginBrowser } = await import('../core/ChromeCdpReloginBrowser.js'); return new ChromeCdpReloginBrowser({ userDataDir: profileDir, passkeyMode: true, headless: true, launchTimeoutMs: 30_000, operationTimeoutMs: 20_000 }); }, poolLink: _poolLink ?? undefined, poolPollCache: _poolPollCache ?? undefined, sessionPoolE2EResultStore, proxyCoordinator, topicIntentStore, topicIntentArcCheck, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, briefDeps, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper, agentWorktreeReaper, externalHogSentinel, orphanedWorkSentinel, mcpProcessReaper, codexArmSessionSweeper, geminiLoopRunner, sleepController, agentActivityState, reapLog, resumeQueue, resumeDrainer, autonomousLivenessReconciler, enforcedTerminationStatus: () => enforcedTerminationWatchdog?.guardStatus() ?? null, prHandLease: prHandLease ?? undefined, standDownRegistry: _standDownRegistry ?? undefined, standDownAudit: _standDownAudit ?? undefined, operatorStopRecorder: recordOperatorStop, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier, liveTestGate, liveTestGateMode, liveTestRunnerCtx });
|
|
30148
|
+
if (_pendingCompactionEvidence)
|
|
30149
|
+
featureEvidence.record('multiMachine.coherenceJournal.replication.compaction', _pendingCompactionEvidence); // Resolve the late-bound topic-operator getter (increment 2e): routing was
|
|
29649
30150
|
const readIdentityProjectionPeerRows = async () => {
|
|
29650
30151
|
const peers = _resolvePeerUrls?.() ?? [];
|
|
29651
30152
|
const extra = config.multiMachine?.peerUrlAllowlist;
|
|
@@ -29996,6 +30497,7 @@ export async function startServer(options) {
|
|
|
29996
30497
|
subjectMachineId: proposed.machineId, epoch: proposed.recoveryEpoch ?? 0,
|
|
29997
30498
|
contentHash: operatorGrantMod.recoveryRootDelegationHash(proposed), dryRun,
|
|
29998
30499
|
});
|
|
30500
|
+
featureEvidence.record('multiMachine.recoveryKeyEscrow', { kind: 'fired', reason: dryRun ? 'would rotate the recovery root from a peer' : 'rotated the recovery root from a peer', context: { machineId: proposed.machineId, recoveryEpoch: proposed.recoveryEpoch ?? 0, dryRun } });
|
|
29999
30501
|
if (dryRun)
|
|
30000
30502
|
return 'would-rotate';
|
|
30001
30503
|
identityStore.apply({
|
|
@@ -30590,10 +31092,14 @@ export async function startServer(options) {
|
|
|
30590
31092
|
// port (force-closes lingering sockets, awaits 'close') BEFORE listen, so the
|
|
30591
31093
|
// gap is sub-second and the supervisor never observes a hole. No-op if the
|
|
30592
31094
|
// beacon was never started (dark) or already failed.
|
|
31095
|
+
// A failed bind happened before the evidence log was wired (at AgentServer construction), so it is kept and written here.
|
|
31096
|
+
if (bootBeaconBindErrorCode)
|
|
31097
|
+
featureEvidence.record('monitoring.bootHealthBeacon', { kind: 'error', reason: 'could not bind during boot', context: { code: bootBeaconBindErrorCode, port: config.port } });
|
|
30593
31098
|
try {
|
|
30594
31099
|
await bootBeacon?.stop();
|
|
30595
31100
|
}
|
|
30596
31101
|
catch (err) {
|
|
31102
|
+
featureEvidence.record('monitoring.bootHealthBeacon', { kind: 'error', reason: 'handoff failed: stop threw', context: { port: config.port, errorName: err instanceof Error ? err.name : 'unknown' } });
|
|
30597
31103
|
// @silent-fallback-ok — a beacon stop failure must not stop the real server
|
|
30598
31104
|
// from binding; logged, and the OS releases the listening socket regardless.
|
|
30599
31105
|
console.error(' Boot health beacon stop failed (continuing to bind real server):', err instanceof Error ? err.message : err);
|
|
@@ -30604,6 +31110,16 @@ export async function startServer(options) {
|
|
|
30604
31110
|
// no per-session write admission.
|
|
30605
31111
|
sessionManager.startMonitoring();
|
|
30606
31112
|
await server.start();
|
|
31113
|
+
// Boot recovery runs before the evidence log exists, so its verdict is recorded here.
|
|
31114
|
+
if (resolveDevAgentGate(config.multiMachine?.recoveryKeyEscrow?.enabled, config)) {
|
|
31115
|
+
const escrowDryRun = config.multiMachine?.recoveryKeyEscrow?.dryRun !== false;
|
|
31116
|
+
featureEvidence.record('multiMachine.recoveryKeyEscrow', {
|
|
31117
|
+
kind: bootRecoveryOutcome === 'disabled' || (_recoveryEscrowEvidence && !_recoveryEscrowEvidence.minted && _recoveryEscrowEvidence.hadRoot) ? 'error'
|
|
31118
|
+
: bootRecoveryOutcome === 'coherence-held' ? 'held' : 'fired',
|
|
31119
|
+
reason: bootRecoveryOutcome === 'disabled' ? 'boot recovery unavailable' : `boot recovery: ${bootRecoveryOutcome}`,
|
|
31120
|
+
context: { outcome: bootRecoveryOutcome, dryRun: escrowDryRun, minted: _recoveryEscrowEvidence?.minted ?? null, hadRoot: _recoveryEscrowEvidence?.hadRoot ?? null, recoveryEpoch: _recoveryEscrowEvidence?.recoveryEpoch ?? null },
|
|
31121
|
+
});
|
|
31122
|
+
}
|
|
30607
31123
|
// After listen: a stop's condition usually turns met across a restart onto the
|
|
30608
31124
|
// fixed version, and the wake brief sends a session straight to a route.
|
|
30609
31125
|
agentStopSurfacer?.start();
|