instar 0.28.76 → 0.28.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dashboard/index.html +486 -0
- package/dist/cli.js +5 -8
- package/dist/cli.js.map +1 -1
- package/dist/commands/discovery.d.ts.map +1 -1
- package/dist/commands/discovery.js +2 -2
- package/dist/commands/discovery.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +22 -4
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/job.d.ts.map +1 -1
- package/dist/commands/job.js +2 -2
- package/dist/commands/job.js.map +1 -1
- package/dist/commands/ledgerCleanup.d.ts.map +1 -1
- package/dist/commands/ledgerCleanup.js +2 -2
- package/dist/commands/ledgerCleanup.js.map +1 -1
- package/dist/commands/listener.d.ts.map +1 -1
- package/dist/commands/listener.js +7 -12
- package/dist/commands/listener.js.map +1 -1
- package/dist/commands/nuke.d.ts.map +1 -1
- package/dist/commands/nuke.js +11 -21
- package/dist/commands/nuke.js.map +1 -1
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +79 -5
- package/dist/commands/server.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +11 -15
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/slack-cli.d.ts.map +1 -1
- package/dist/commands/slack-cli.js +5 -8
- package/dist/commands/slack-cli.js.map +1 -1
- package/dist/commands/whatsapp.d.ts.map +1 -1
- package/dist/commands/whatsapp.js +2 -2
- package/dist/commands/whatsapp.js.map +1 -1
- package/dist/commands/worktree.d.ts.map +1 -1
- package/dist/commands/worktree.js +2 -2
- package/dist/commands/worktree.js.map +1 -1
- package/dist/core/AgentConnector.d.ts.map +1 -1
- package/dist/core/AgentConnector.js +9 -10
- package/dist/core/AgentConnector.js.map +1 -1
- package/dist/core/AgentRegistry.d.ts.map +1 -1
- package/dist/core/AgentRegistry.js +3 -4
- package/dist/core/AgentRegistry.js.map +1 -1
- package/dist/core/AutoDispatcher.d.ts.map +1 -1
- package/dist/core/AutoDispatcher.js +2 -2
- package/dist/core/AutoDispatcher.js.map +1 -1
- package/dist/core/AutoUpdater.d.ts.map +1 -1
- package/dist/core/AutoUpdater.js +2 -2
- package/dist/core/AutoUpdater.js.map +1 -1
- package/dist/core/AutonomousEvolution.d.ts.map +1 -1
- package/dist/core/AutonomousEvolution.js +2 -2
- package/dist/core/AutonomousEvolution.js.map +1 -1
- package/dist/core/BackupManager.d.ts.map +1 -1
- package/dist/core/BackupManager.js +2 -2
- package/dist/core/BackupManager.js.map +1 -1
- package/dist/core/BranchManager.d.ts.map +1 -1
- package/dist/core/BranchManager.js +3 -3
- package/dist/core/BranchManager.js.map +1 -1
- package/dist/core/CaffeinateManager.d.ts.map +1 -1
- package/dist/core/CaffeinateManager.js +2 -2
- package/dist/core/CaffeinateManager.js.map +1 -1
- package/dist/core/DeferredDispatchTracker.d.ts.map +1 -1
- package/dist/core/DeferredDispatchTracker.js +2 -2
- package/dist/core/DeferredDispatchTracker.js.map +1 -1
- package/dist/core/DispatchManager.d.ts.map +1 -1
- package/dist/core/DispatchManager.js +3 -4
- package/dist/core/DispatchManager.js.map +1 -1
- package/dist/core/EvolutionManager.d.ts.map +1 -1
- package/dist/core/EvolutionManager.js +2 -2
- package/dist/core/EvolutionManager.js.map +1 -1
- package/dist/core/ExecutionJournal.d.ts.map +1 -1
- package/dist/core/ExecutionJournal.js +2 -2
- package/dist/core/ExecutionJournal.js.map +1 -1
- package/dist/core/FeedbackManager.d.ts.map +1 -1
- package/dist/core/FeedbackManager.js +2 -2
- package/dist/core/FeedbackManager.js.map +1 -1
- package/dist/core/FileClassifier.d.ts.map +1 -1
- package/dist/core/FileClassifier.js +8 -17
- package/dist/core/FileClassifier.js.map +1 -1
- package/dist/core/ForegroundRestartWatcher.d.ts.map +1 -1
- package/dist/core/ForegroundRestartWatcher.js +3 -4
- package/dist/core/ForegroundRestartWatcher.js.map +1 -1
- package/dist/core/GitStateManager.d.ts.map +1 -1
- package/dist/core/GitStateManager.js +3 -12
- package/dist/core/GitStateManager.js.map +1 -1
- package/dist/core/GitSync.d.ts.map +1 -1
- package/dist/core/GitSync.js +6 -6
- package/dist/core/GitSync.js.map +1 -1
- package/dist/core/GlobalInstallCleanup.d.ts.map +1 -1
- package/dist/core/GlobalInstallCleanup.js +3 -4
- package/dist/core/GlobalInstallCleanup.js.map +1 -1
- package/dist/core/GlobalSecretStore.d.ts.map +1 -1
- package/dist/core/GlobalSecretStore.js +3 -4
- package/dist/core/GlobalSecretStore.js.map +1 -1
- package/dist/core/HandoffManager.d.ts.map +1 -1
- package/dist/core/HandoffManager.js +5 -5
- package/dist/core/HandoffManager.js.map +1 -1
- package/dist/core/JargonDetector.d.ts +28 -0
- package/dist/core/JargonDetector.d.ts.map +1 -0
- package/dist/core/JargonDetector.js +59 -0
- package/dist/core/JargonDetector.js.map +1 -0
- package/dist/core/LedgerSessionRegistry.d.ts.map +1 -1
- package/dist/core/LedgerSessionRegistry.js +2 -2
- package/dist/core/LedgerSessionRegistry.js.map +1 -1
- package/dist/core/MachineIdentity.d.ts.map +1 -1
- package/dist/core/MachineIdentity.js +2 -2
- package/dist/core/MachineIdentity.js.map +1 -1
- package/dist/core/MessagingToneGate.d.ts +42 -5
- package/dist/core/MessagingToneGate.d.ts.map +1 -1
- package/dist/core/MessagingToneGate.js +40 -6
- package/dist/core/MessagingToneGate.js.map +1 -1
- package/dist/core/ParallelDevWiring.d.ts.map +1 -1
- package/dist/core/ParallelDevWiring.js +3 -6
- package/dist/core/ParallelDevWiring.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +26 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +249 -46
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/ProjectMapper.d.ts.map +1 -1
- package/dist/core/ProjectMapper.js +5 -11
- package/dist/core/ProjectMapper.js.map +1 -1
- package/dist/core/RelationshipManager.d.ts.map +1 -1
- package/dist/core/RelationshipManager.js +4 -5
- package/dist/core/RelationshipManager.js.map +1 -1
- package/dist/core/SafeGitExecutor.d.ts +11 -5
- package/dist/core/SafeGitExecutor.d.ts.map +1 -1
- package/dist/core/SafeGitExecutor.js +87 -1
- package/dist/core/SafeGitExecutor.js.map +1 -1
- package/dist/core/ScopeVerifier.d.ts.map +1 -1
- package/dist/core/ScopeVerifier.js +3 -6
- package/dist/core/ScopeVerifier.js.map +1 -1
- package/dist/core/SecretStore.d.ts.map +1 -1
- package/dist/core/SecretStore.js +2 -2
- package/dist/core/SecretStore.js.map +1 -1
- package/dist/core/SharedStateLedger.d.ts.map +1 -1
- package/dist/core/SharedStateLedger.js +2 -2
- package/dist/core/SharedStateLedger.js.map +1 -1
- package/dist/core/SoulManager.d.ts.map +1 -1
- package/dist/core/SoulManager.js +3 -4
- package/dist/core/SoulManager.js.map +1 -1
- package/dist/core/StateManager.d.ts.map +1 -1
- package/dist/core/StateManager.js +4 -6
- package/dist/core/StateManager.js.map +1 -1
- package/dist/core/SyncOrchestrator.d.ts.map +1 -1
- package/dist/core/SyncOrchestrator.js +6 -7
- package/dist/core/SyncOrchestrator.js.map +1 -1
- package/dist/core/UpdateChecker.d.ts.map +1 -1
- package/dist/core/UpdateChecker.js +3 -4
- package/dist/core/UpdateChecker.js.map +1 -1
- package/dist/core/UpgradeGuideProcessor.d.ts.map +1 -1
- package/dist/core/UpgradeGuideProcessor.js +3 -4
- package/dist/core/UpgradeGuideProcessor.js.map +1 -1
- package/dist/core/WorktreeManager.d.ts.map +1 -1
- package/dist/core/WorktreeManager.js +9 -14
- package/dist/core/WorktreeManager.js.map +1 -1
- package/dist/knowledge/KnowledgeManager.d.ts.map +1 -1
- package/dist/knowledge/KnowledgeManager.js +2 -2
- package/dist/knowledge/KnowledgeManager.js.map +1 -1
- package/dist/lifeline/ServerSupervisor.d.ts +28 -0
- package/dist/lifeline/ServerSupervisor.d.ts.map +1 -1
- package/dist/lifeline/ServerSupervisor.js +171 -73
- package/dist/lifeline/ServerSupervisor.js.map +1 -1
- package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
- package/dist/lifeline/TelegramLifeline.js +10 -4
- package/dist/lifeline/TelegramLifeline.js.map +1 -1
- package/dist/lifeline/detectLaunchdSupervised.d.ts +43 -0
- package/dist/lifeline/detectLaunchdSupervised.d.ts.map +1 -0
- package/dist/lifeline/detectLaunchdSupervised.js +106 -0
- package/dist/lifeline/detectLaunchdSupervised.js.map +1 -0
- package/dist/lifeline/droppedMessages.d.ts.map +1 -1
- package/dist/lifeline/droppedMessages.js +2 -2
- package/dist/lifeline/droppedMessages.js.map +1 -1
- package/dist/memory/EpisodicMemory.d.ts.map +1 -1
- package/dist/memory/EpisodicMemory.js +2 -2
- package/dist/memory/EpisodicMemory.js.map +1 -1
- package/dist/memory/TopicMemory.d.ts.map +1 -1
- package/dist/memory/TopicMemory.js +5 -8
- package/dist/memory/TopicMemory.js.map +1 -1
- package/dist/messaging/AgentTokenManager.d.ts.map +1 -1
- package/dist/messaging/AgentTokenManager.js +2 -2
- package/dist/messaging/AgentTokenManager.js.map +1 -1
- package/dist/messaging/DropPickup.d.ts.map +1 -1
- package/dist/messaging/DropPickup.js +2 -2
- package/dist/messaging/DropPickup.js.map +1 -1
- package/dist/messaging/GitSyncTransport.d.ts.map +1 -1
- package/dist/messaging/GitSyncTransport.js +4 -6
- package/dist/messaging/GitSyncTransport.js.map +1 -1
- package/dist/messaging/MessageStore.d.ts.map +1 -1
- package/dist/messaging/MessageStore.js +3 -4
- package/dist/messaging/MessageStore.js.map +1 -1
- package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
- package/dist/messaging/TelegramAdapter.js +5 -8
- package/dist/messaging/TelegramAdapter.js.map +1 -1
- package/dist/messaging/backends/BaileysBackend.d.ts.map +1 -1
- package/dist/messaging/backends/BaileysBackend.js +3 -4
- package/dist/messaging/backends/BaileysBackend.js.map +1 -1
- package/dist/messaging/local-tone-check.d.ts +61 -0
- package/dist/messaging/local-tone-check.d.ts.map +1 -0
- package/dist/messaging/local-tone-check.js +78 -0
- package/dist/messaging/local-tone-check.js.map +1 -0
- package/dist/messaging/pending-relay-store.d.ts +153 -0
- package/dist/messaging/pending-relay-store.d.ts.map +1 -0
- package/dist/messaging/pending-relay-store.js +351 -0
- package/dist/messaging/pending-relay-store.js.map +1 -0
- package/dist/messaging/secret-patterns.d.ts +35 -0
- package/dist/messaging/secret-patterns.d.ts.map +1 -0
- package/dist/messaging/secret-patterns.js +70 -0
- package/dist/messaging/secret-patterns.js.map +1 -0
- package/dist/messaging/shared/EncryptedAuthStore.d.ts.map +1 -1
- package/dist/messaging/shared/EncryptedAuthStore.js +3 -4
- package/dist/messaging/shared/EncryptedAuthStore.js.map +1 -1
- package/dist/messaging/shared/MessageLogger.d.ts.map +1 -1
- package/dist/messaging/shared/MessageLogger.js +2 -2
- package/dist/messaging/shared/MessageLogger.js.map +1 -1
- package/dist/messaging/shared/PrivacyConsent.d.ts.map +1 -1
- package/dist/messaging/shared/PrivacyConsent.js +2 -2
- package/dist/messaging/shared/PrivacyConsent.js.map +1 -1
- package/dist/messaging/shared/SessionChannelRegistry.d.ts.map +1 -1
- package/dist/messaging/shared/SessionChannelRegistry.js +2 -2
- package/dist/messaging/shared/SessionChannelRegistry.js.map +1 -1
- package/dist/messaging/system-templates.d.ts +87 -0
- package/dist/messaging/system-templates.d.ts.map +1 -0
- package/dist/messaging/system-templates.js +236 -0
- package/dist/messaging/system-templates.js.map +1 -0
- package/dist/messaging/whoami-cache.d.ts +66 -0
- package/dist/messaging/whoami-cache.d.ts.map +1 -0
- package/dist/messaging/whoami-cache.js +149 -0
- package/dist/messaging/whoami-cache.js.map +1 -0
- package/dist/moltbridge/ProfileCompiler.d.ts.map +1 -1
- package/dist/moltbridge/ProfileCompiler.js +13 -7
- package/dist/moltbridge/ProfileCompiler.js.map +1 -1
- package/dist/monitoring/CommitmentTracker.d.ts.map +1 -1
- package/dist/monitoring/CommitmentTracker.js +2 -2
- package/dist/monitoring/CommitmentTracker.js.map +1 -1
- package/dist/monitoring/CredentialProvider.d.ts.map +1 -1
- package/dist/monitoring/CredentialProvider.js +2 -2
- package/dist/monitoring/CredentialProvider.js.map +1 -1
- package/dist/monitoring/DegradationReporter.d.ts +41 -0
- package/dist/monitoring/DegradationReporter.d.ts.map +1 -1
- package/dist/monitoring/DegradationReporter.js +96 -4
- package/dist/monitoring/DegradationReporter.js.map +1 -1
- package/dist/monitoring/HealthChecker.d.ts.map +1 -1
- package/dist/monitoring/HealthChecker.js +2 -2
- package/dist/monitoring/HealthChecker.js.map +1 -1
- package/dist/monitoring/HookEventReceiver.d.ts.map +1 -1
- package/dist/monitoring/HookEventReceiver.js +2 -2
- package/dist/monitoring/HookEventReceiver.js.map +1 -1
- package/dist/monitoring/InstructionsVerifier.d.ts.map +1 -1
- package/dist/monitoring/InstructionsVerifier.js +2 -2
- package/dist/monitoring/InstructionsVerifier.js.map +1 -1
- package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
- package/dist/monitoring/PresenceProxy.js +5 -8
- package/dist/monitoring/PresenceProxy.js.map +1 -1
- package/dist/monitoring/QuotaTracker.d.ts.map +1 -1
- package/dist/monitoring/QuotaTracker.js +2 -2
- package/dist/monitoring/QuotaTracker.js.map +1 -1
- package/dist/monitoring/SessionMigrator.d.ts.map +1 -1
- package/dist/monitoring/SessionMigrator.js +2 -2
- package/dist/monitoring/SessionMigrator.js.map +1 -1
- package/dist/monitoring/SessionRecovery.d.ts.map +1 -1
- package/dist/monitoring/SessionRecovery.js +2 -2
- package/dist/monitoring/SessionRecovery.js.map +1 -1
- package/dist/monitoring/TelemetryAuth.d.ts.map +1 -1
- package/dist/monitoring/TelemetryAuth.js +3 -4
- package/dist/monitoring/TelemetryAuth.js.map +1 -1
- package/dist/monitoring/TokenLedger.d.ts +130 -0
- package/dist/monitoring/TokenLedger.d.ts.map +1 -0
- package/dist/monitoring/TokenLedger.js +523 -0
- package/dist/monitoring/TokenLedger.js.map +1 -0
- package/dist/monitoring/TokenLedgerPoller.d.ts +26 -0
- package/dist/monitoring/TokenLedgerPoller.d.ts.map +1 -0
- package/dist/monitoring/TokenLedgerPoller.js +44 -0
- package/dist/monitoring/TokenLedgerPoller.js.map +1 -0
- package/dist/monitoring/TriageOrchestrator.d.ts.map +1 -1
- package/dist/monitoring/TriageOrchestrator.js +3 -4
- package/dist/monitoring/TriageOrchestrator.js.map +1 -1
- package/dist/monitoring/WorktreeReaper.d.ts.map +1 -1
- package/dist/monitoring/WorktreeReaper.js +5 -7
- package/dist/monitoring/WorktreeReaper.js.map +1 -1
- package/dist/monitoring/delivery-failure-sentinel/recovery-policy.d.ts +83 -0
- package/dist/monitoring/delivery-failure-sentinel/recovery-policy.d.ts.map +1 -0
- package/dist/monitoring/delivery-failure-sentinel/recovery-policy.js +218 -0
- package/dist/monitoring/delivery-failure-sentinel/recovery-policy.js.map +1 -0
- package/dist/monitoring/delivery-failure-sentinel.d.ts +177 -0
- package/dist/monitoring/delivery-failure-sentinel.d.ts.map +1 -0
- package/dist/monitoring/delivery-failure-sentinel.js +598 -0
- package/dist/monitoring/delivery-failure-sentinel.js.map +1 -0
- package/dist/monitoring/probes/PlatformProbe.d.ts.map +1 -1
- package/dist/monitoring/probes/PlatformProbe.js +3 -4
- package/dist/monitoring/probes/PlatformProbe.js.map +1 -1
- package/dist/monitoring/templates-drift-verifier.d.ts +109 -0
- package/dist/monitoring/templates-drift-verifier.d.ts.map +1 -0
- package/dist/monitoring/templates-drift-verifier.js +324 -0
- package/dist/monitoring/templates-drift-verifier.js.map +1 -0
- package/dist/paste/PasteManager.d.ts.map +1 -1
- package/dist/paste/PasteManager.js +5 -8
- package/dist/paste/PasteManager.js.map +1 -1
- package/dist/publishing/PrivateViewer.d.ts.map +1 -1
- package/dist/publishing/PrivateViewer.js +2 -2
- package/dist/publishing/PrivateViewer.js.map +1 -1
- package/dist/scheduler/JobScheduler.d.ts.map +1 -1
- package/dist/scheduler/JobScheduler.js +2 -2
- package/dist/scheduler/JobScheduler.js.map +1 -1
- package/dist/server/AgentServer.d.ts +22 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +199 -1
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/WebSocketManager.d.ts +11 -0
- package/dist/server/WebSocketManager.d.ts.map +1 -1
- package/dist/server/WebSocketManager.js +28 -0
- package/dist/server/WebSocketManager.js.map +1 -1
- package/dist/server/boot-id.d.ts +58 -0
- package/dist/server/boot-id.d.ts.map +1 -0
- package/dist/server/boot-id.js +121 -0
- package/dist/server/boot-id.js.map +1 -0
- package/dist/server/middleware.d.ts +14 -1
- package/dist/server/middleware.d.ts.map +1 -1
- package/dist/server/middleware.js +81 -1
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/routes.d.ts +76 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +626 -11
- package/dist/server/routes.js.map +1 -1
- package/dist/threadline/AgentDiscovery.d.ts.map +1 -1
- package/dist/threadline/AgentDiscovery.js +2 -2
- package/dist/threadline/AgentDiscovery.js.map +1 -1
- package/dist/threadline/AgentTrustManager.d.ts.map +1 -1
- package/dist/threadline/AgentTrustManager.js +2 -2
- package/dist/threadline/AgentTrustManager.js.map +1 -1
- package/dist/threadline/BackfillCore.d.ts +70 -0
- package/dist/threadline/BackfillCore.d.ts.map +1 -0
- package/dist/threadline/BackfillCore.js +117 -0
- package/dist/threadline/BackfillCore.js.map +1 -0
- package/dist/threadline/CircuitBreaker.d.ts.map +1 -1
- package/dist/threadline/CircuitBreaker.js +2 -2
- package/dist/threadline/CircuitBreaker.js.map +1 -1
- package/dist/threadline/ComputeMeter.d.ts.map +1 -1
- package/dist/threadline/ComputeMeter.js +2 -2
- package/dist/threadline/ComputeMeter.js.map +1 -1
- package/dist/threadline/ContextThreadMap.d.ts.map +1 -1
- package/dist/threadline/ContextThreadMap.js +2 -2
- package/dist/threadline/ContextThreadMap.js.map +1 -1
- package/dist/threadline/HeartbeatWatchdog.d.ts +78 -0
- package/dist/threadline/HeartbeatWatchdog.d.ts.map +1 -0
- package/dist/threadline/HeartbeatWatchdog.js +212 -0
- package/dist/threadline/HeartbeatWatchdog.js.map +1 -0
- package/dist/threadline/HeartbeatWriter.d.ts +79 -0
- package/dist/threadline/HeartbeatWriter.d.ts.map +1 -0
- package/dist/threadline/HeartbeatWriter.js +109 -0
- package/dist/threadline/HeartbeatWriter.js.map +1 -0
- package/dist/threadline/InvitationManager.d.ts.map +1 -1
- package/dist/threadline/InvitationManager.js +2 -2
- package/dist/threadline/InvitationManager.js.map +1 -1
- package/dist/threadline/ListenerSessionManager.d.ts +59 -0
- package/dist/threadline/ListenerSessionManager.d.ts.map +1 -1
- package/dist/threadline/ListenerSessionManager.js +79 -0
- package/dist/threadline/ListenerSessionManager.js.map +1 -1
- package/dist/threadline/MCPAuth.d.ts.map +1 -1
- package/dist/threadline/MCPAuth.js +2 -2
- package/dist/threadline/MCPAuth.js.map +1 -1
- package/dist/threadline/PipeSessionSpawner.d.ts.map +1 -1
- package/dist/threadline/PipeSessionSpawner.js +3 -4
- package/dist/threadline/PipeSessionSpawner.js.map +1 -1
- package/dist/threadline/RateLimiter.d.ts.map +1 -1
- package/dist/threadline/RateLimiter.js +2 -2
- package/dist/threadline/RateLimiter.js.map +1 -1
- package/dist/threadline/RelaySpawnFailureHandler.d.ts +53 -0
- package/dist/threadline/RelaySpawnFailureHandler.d.ts.map +1 -0
- package/dist/threadline/RelaySpawnFailureHandler.js +73 -0
- package/dist/threadline/RelaySpawnFailureHandler.js.map +1 -0
- package/dist/threadline/SessionLifecycle.d.ts.map +1 -1
- package/dist/threadline/SessionLifecycle.js +2 -2
- package/dist/threadline/SessionLifecycle.js.map +1 -1
- package/dist/threadline/SpawnLedger.d.ts +94 -0
- package/dist/threadline/SpawnLedger.d.ts.map +1 -0
- package/dist/threadline/SpawnLedger.js +194 -0
- package/dist/threadline/SpawnLedger.js.map +1 -0
- package/dist/threadline/SpawnNonce.d.ts +49 -0
- package/dist/threadline/SpawnNonce.d.ts.map +1 -0
- package/dist/threadline/SpawnNonce.js +99 -0
- package/dist/threadline/SpawnNonce.js.map +1 -0
- package/dist/threadline/TelegramBridge.d.ts +140 -0
- package/dist/threadline/TelegramBridge.d.ts.map +1 -0
- package/dist/threadline/TelegramBridge.js +224 -0
- package/dist/threadline/TelegramBridge.js.map +1 -0
- package/dist/threadline/TelegramBridgeConfig.d.ts +79 -0
- package/dist/threadline/TelegramBridgeConfig.d.ts.map +1 -0
- package/dist/threadline/TelegramBridgeConfig.js +168 -0
- package/dist/threadline/TelegramBridgeConfig.js.map +1 -0
- package/dist/threadline/ThreadlineBootstrap.d.ts.map +1 -1
- package/dist/threadline/ThreadlineBootstrap.js +2 -2
- package/dist/threadline/ThreadlineBootstrap.js.map +1 -1
- package/dist/threadline/ThreadlineMCPServer.d.ts.map +1 -1
- package/dist/threadline/ThreadlineMCPServer.js +5 -0
- package/dist/threadline/ThreadlineMCPServer.js.map +1 -1
- package/dist/threadline/ThreadlineObservability.d.ts +95 -0
- package/dist/threadline/ThreadlineObservability.d.ts.map +1 -0
- package/dist/threadline/ThreadlineObservability.js +310 -0
- package/dist/threadline/ThreadlineObservability.js.map +1 -0
- package/dist/threadline/WakeSocketServer.d.ts.map +1 -1
- package/dist/threadline/WakeSocketServer.js +3 -4
- package/dist/threadline/WakeSocketServer.js.map +1 -1
- package/dist/threadline/listener-daemon.d.ts.map +1 -1
- package/dist/threadline/listener-daemon.js +3 -4
- package/dist/threadline/listener-daemon.js.map +1 -1
- package/dist/users/UserManager.d.ts.map +1 -1
- package/dist/users/UserManager.js +2 -2
- package/dist/users/UserManager.js.map +1 -1
- package/dist/users/UserOnboarding.d.ts.map +1 -1
- package/dist/users/UserOnboarding.js +2 -2
- package/dist/users/UserOnboarding.js.map +1 -1
- package/dist/utils/jsonl-rotation.d.ts.map +1 -1
- package/dist/utils/jsonl-rotation.js +2 -2
- package/dist/utils/jsonl-rotation.js.map +1 -1
- package/package.json +1 -1
- package/scripts/analyze-release.js +7 -12
- package/scripts/check-contract-evidence.js +27 -10
- package/scripts/fix-better-sqlite3.cjs +0 -2
- package/scripts/instar-dev-precommit.js +0 -2
- package/scripts/lint-no-direct-destructive.js +24 -4
- package/scripts/lint-template-sha-history.ts +183 -0
- package/scripts/migrate-incident-2026-04-17.mjs +2 -2
- package/scripts/run-migration.js +500 -0
- package/scripts/test-bootstrap-relay.mjs +2 -2
- package/scripts/threadline-bridge-backfill.mjs +379 -0
- package/scripts/verify-deployed-templates.ts +87 -0
- package/src/data/builtin-manifest.json +140 -132
- package/src/templates/scripts/git-sync-gate.sh +0 -4
- package/src/templates/scripts/telegram-reply.sh +318 -13
- package/upgrades/0.28.77.md +133 -0
- package/upgrades/0.28.78.md +90 -0
- package/upgrades/side-effects/agent-health-alert-authority-routing.md +121 -0
- package/upgrades/side-effects/comprehensive-destructive-tool-containment-migration.md +82 -0
- package/upgrades/side-effects/deferral-detector-orphan-todo.md +101 -0
- package/upgrades/side-effects/lifeline-self-heal-hardening.md +151 -0
- package/upgrades/side-effects/relay-spawn-ghost-reply-phase1.md +139 -0
- package/upgrades/side-effects/telegram-delivery-robustness-layer-2.md +320 -0
- package/upgrades/side-effects/telegram-delivery-robustness-layer-3.md +202 -0
- package/upgrades/side-effects/telegram-delivery-robustness-layer-7.md +339 -0
- package/upgrades/side-effects/telegram-delivery-robustness.md +178 -0
- package/upgrades/side-effects/threadline-bridge-backfill.md +203 -0
- package/upgrades/side-effects/threadline-canonical-inbox-write.md +218 -0
- package/upgrades/side-effects/threadline-observability-tab.md +206 -0
- package/upgrades/side-effects/threadline-tg-bridge-module.md +196 -0
- package/upgrades/side-effects/threadline-tg-bridge-settings-surface.md +208 -0
- package/upgrades/side-effects/token-ledger-bounded-scan.md +230 -0
- package/upgrades/side-effects/token-ledger-phase1.md +123 -0
- package/upgrades/NEXT.md +0 -53
- /package/upgrades/side-effects/{telegram-lifeline-version-missing-info.md → 0.28.76.md} +0 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Side-Effects Review — Threadline → Telegram Bridge Module
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `threadline-tg-bridge-module`
|
|
4
|
+
**Date:** `2026-05-02`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `self (incident-grounded reasoning)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Ships the actual **bridge module** that mirrors threadline messages into
|
|
11
|
+
per-thread Telegram topics — third of five deliverables in topic-8686.
|
|
12
|
+
|
|
13
|
+
Builds on:
|
|
14
|
+
- (a) Canonical inbox write-path fix — PR #113, commit `9cc3e9af` — gives
|
|
15
|
+
the bridge a single source of truth for inbound traffic.
|
|
16
|
+
- (2) Settings surface — PR #114 — provides the toggles + allow/deny
|
|
17
|
+
list policy the bridge consults on every message.
|
|
18
|
+
|
|
19
|
+
Files added:
|
|
20
|
+
|
|
21
|
+
- `src/threadline/TelegramBridge.ts` — bridge class. Methods:
|
|
22
|
+
- `mirrorInbound(evt)` — relay handler calls this after the canonical
|
|
23
|
+
inbox write; auto-creates a topic if config policy allows, otherwise
|
|
24
|
+
no-op or mirrors into existing.
|
|
25
|
+
- `mirrorOutbound(evt)` — `/threadline/relay-send` calls this after
|
|
26
|
+
success; mirrors into existing topic only (outbound never auto-creates).
|
|
27
|
+
- Persistence in `.instar/threadline/telegram-bridge-bindings.json`
|
|
28
|
+
(mode `0o600`).
|
|
29
|
+
|
|
30
|
+
Files modified:
|
|
31
|
+
|
|
32
|
+
- `src/commands/server.ts` — instantiates `TelegramBridge` after the
|
|
33
|
+
Telegram adapter is constructed; passes through to AgentServer; the
|
|
34
|
+
relay handler's `gate-passed` listener fires `mirrorInbound` async.
|
|
35
|
+
- `src/server/routes.ts` — `RouteContext.telegramBridge` typed; the
|
|
36
|
+
`/threadline/relay-send` route fires `mirrorOutbound` on both the
|
|
37
|
+
local-delivery and relay-delivery success paths.
|
|
38
|
+
- `src/server/AgentServer.ts` — accepts `options.telegramBridge`,
|
|
39
|
+
passes through `routeCtx`.
|
|
40
|
+
|
|
41
|
+
Tests added: 18 unit cases in `tests/unit/TelegramBridge.test.ts`.
|
|
42
|
+
|
|
43
|
+
## Decision-point inventory
|
|
44
|
+
|
|
45
|
+
- `TelegramBridge.mirrorInbound` — **add** — relay-only mirror with
|
|
46
|
+
auto-create gate via `TelegramBridgeConfig`.
|
|
47
|
+
- `TelegramBridge.mirrorOutbound` — **add** — relay-only mirror into
|
|
48
|
+
existing topic; never auto-creates.
|
|
49
|
+
- `TelegramBridge.buildTopicName` — **add** — `{local}↔{remote} — {subject}`
|
|
50
|
+
with truncation to 96 chars (Telegram 128 cap with headroom).
|
|
51
|
+
- `TelegramBridgeBindingsFile` — **add** — version=1 JSON file persisted
|
|
52
|
+
at `.instar/threadline/telegram-bridge-bindings.json`.
|
|
53
|
+
- Relay handler in `server.ts` — **modify** — new `mirrorInbound` call
|
|
54
|
+
AFTER the canonical inbox write, fire-and-forget with `.catch()`.
|
|
55
|
+
- `/threadline/relay-send` route — **modify** — new `mirrorOutbound`
|
|
56
|
+
calls in BOTH success paths (local + relay); fire-and-forget.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 1. Over-block
|
|
61
|
+
|
|
62
|
+
**What legitimate inputs does this change reject that it shouldn't?**
|
|
63
|
+
|
|
64
|
+
The bridge is **relay-only**: it has zero blocking authority. It cannot
|
|
65
|
+
reject any input, route, or send. The only gate is "should I post this
|
|
66
|
+
into Telegram?" — and the answer is decided by `TelegramBridgeConfig`,
|
|
67
|
+
which was reviewed and pinned in PR #114.
|
|
68
|
+
|
|
69
|
+
False over-blocks are not possible at this layer. If the user reports
|
|
70
|
+
"a message I expected to see in Telegram didn't show up", the cause is
|
|
71
|
+
either (a) bridge disabled (master switch off), (b) auto-create denied
|
|
72
|
+
because the remote agent isn't allow-listed and `autoCreateTopics=false`,
|
|
73
|
+
or (c) the underlying Telegram API call failed (logged via the bridge's
|
|
74
|
+
warn channel, not surfaced as an error to the routing path).
|
|
75
|
+
|
|
76
|
+
## 2. Under-block
|
|
77
|
+
|
|
78
|
+
**What failure modes does this still miss?**
|
|
79
|
+
|
|
80
|
+
- **No retry on transient Telegram failures.** A 429 / 5xx from Telegram
|
|
81
|
+
during `findOrCreateForumTopic` or `sendToTopic` is logged and skipped.
|
|
82
|
+
No queue, no exponential backoff. Acceptable: the bridge is observability,
|
|
83
|
+
not delivery — message liveness matters for the threadline relay, not
|
|
84
|
+
for the Telegram mirror. A future PR can add a delivery queue if losing
|
|
85
|
+
the occasional mirror becomes a real complaint.
|
|
86
|
+
- **Inbound from a relay that uses a different `threadId` than the
|
|
87
|
+
outbound send.** The bridge keys bindings by `threadId`, which is the
|
|
88
|
+
threadline-side id. As long as both sides use a consistent thread id
|
|
89
|
+
(which they do post-(a)), the binding is stable. If a thread-id
|
|
90
|
+
divergence sneaks in (e.g. the outbound side mints a fresh id), the
|
|
91
|
+
outbound mirror returns `no-binding` and silently no-ops. This is the
|
|
92
|
+
documented behavior; the canonical inbox in (a) is unaffected.
|
|
93
|
+
- **No de-duplication across rapid-fire same-thread inbound.** If the
|
|
94
|
+
relay handler is invoked twice for the same `messageId`, the bridge
|
|
95
|
+
will post twice. Out of scope for this PR — same-thread rapid-fire
|
|
96
|
+
is handled at the relay layer (existing pipe-mode guard) and the
|
|
97
|
+
threadline replay-gate (already enforced by the relay client).
|
|
98
|
+
|
|
99
|
+
## 3. Level-of-abstraction fit
|
|
100
|
+
|
|
101
|
+
The split is the same one used in (2):
|
|
102
|
+
|
|
103
|
+
- **TelegramBridgeConfig** owns *whether* to mirror (validation + policy).
|
|
104
|
+
- **TelegramBridge** owns *how* to mirror (binding lookup, topic creation,
|
|
105
|
+
HTTP call, body formatting).
|
|
106
|
+
- The relay handler and `/threadline/relay-send` route own *when* to
|
|
107
|
+
mirror (event firing).
|
|
108
|
+
|
|
109
|
+
The bridge depends only on a `TelegramSink` interface (subset of
|
|
110
|
+
`TelegramAdapter`'s `findOrCreateForumTopic` + `sendToTopic`). Tests
|
|
111
|
+
inject a fake sink to exercise success and failure paths without a
|
|
112
|
+
running Telegram. This keeps the bridge testable and the dependency
|
|
113
|
+
surface narrow.
|
|
114
|
+
|
|
115
|
+
## 4. Signal-vs-authority compliance
|
|
116
|
+
|
|
117
|
+
- **Signal:** the gate-passed inbox event (already authorized by
|
|
118
|
+
`InboundMessageGate` upstream); the threadline_send → relay-send
|
|
119
|
+
outbound success.
|
|
120
|
+
- **Authority:** `TelegramBridgeConfig` decides whether the bridge runs
|
|
121
|
+
at all. The bridge itself emits zero decisions back to the routing
|
|
122
|
+
layer — `mirrorInbound` and `mirrorOutbound` return `{posted, reason}`
|
|
123
|
+
for observability only; nothing in the routing path inspects that
|
|
124
|
+
return value. This is the canonical signal-vs-authority pattern: the
|
|
125
|
+
bridge is a low-context observer; the higher-level intelligent gate
|
|
126
|
+
(config + the existing inbound gate) holds blocking authority.
|
|
127
|
+
|
|
128
|
+
## 5. Interactions
|
|
129
|
+
|
|
130
|
+
- **Canonical inbox (PR #113).** The bridge fires AFTER the canonical
|
|
131
|
+
inbox write at relay-ingest. Two writes — one local audit, one
|
|
132
|
+
Telegram mirror — both flow from the same event. No coupling: if the
|
|
133
|
+
canonical write fails, the bridge call still runs (and vice versa).
|
|
134
|
+
- **`telegram-reply.sh` pipeline.** The bridge does NOT use this
|
|
135
|
+
pipeline — it calls TelegramAdapter primitives directly, bypassing
|
|
136
|
+
the agent-reply pre-tone-gate path. There is no double-fire because
|
|
137
|
+
`telegram-reply` is for agent → user replies tied to specific topics,
|
|
138
|
+
whereas the bridge writes into bridge-owned topics distinguished by
|
|
139
|
+
the `{local}↔{remote}` naming convention. If the user runs
|
|
140
|
+
`/link <session>` to bind a session to a bridge topic, that's the
|
|
141
|
+
user's explicit choice; the bridge doesn't generate that overlap by itself.
|
|
142
|
+
- **Spawn-session prompt.** The bridge does NOT replace the existing
|
|
143
|
+
spawn-session orchestration. The relay handler still spawns Claude
|
|
144
|
+
Code sessions on inbound; the bridge runs alongside, purely for user
|
|
145
|
+
visibility.
|
|
146
|
+
- **`topic-session-registry.json`.** The bridge maintains its own,
|
|
147
|
+
separate file (`telegram-bridge-bindings.json`) so it does not
|
|
148
|
+
collide with session ↔ topic bindings. Reusing
|
|
149
|
+
`topic-session-registry.json` would have conflated two distinct
|
|
150
|
+
concerns (bridge bindings = thread → topic; session registry =
|
|
151
|
+
session ↔ topic).
|
|
152
|
+
|
|
153
|
+
## 6. Rollback cost
|
|
154
|
+
|
|
155
|
+
- Set `enabled=false` via the dashboard or `PATCH
|
|
156
|
+
/threadline/telegram-bridge/config`. Bridge stops mirroring on the
|
|
157
|
+
next event. Existing bindings stay in the file (no dangling Telegram
|
|
158
|
+
topics get cleaned up — they continue to exist in Telegram but the
|
|
159
|
+
bridge stops feeding them).
|
|
160
|
+
- Drop the bridge module entirely: remove the
|
|
161
|
+
`TelegramBridge` import + instantiation in server.ts + the two route
|
|
162
|
+
hooks. Settings UI from (2) keeps working unchanged. Bindings file
|
|
163
|
+
becomes an orphaned `.instar/threadline/telegram-bridge-bindings.json`
|
|
164
|
+
on disk; safe to leave.
|
|
165
|
+
- No database migrations, no Telegram-side cleanup, no schema changes.
|
|
166
|
+
|
|
167
|
+
## Plan if a regression appears
|
|
168
|
+
|
|
169
|
+
- **Symptom: Telegram noise.** Verify settings — the user can flip
|
|
170
|
+
`enabled=false` instantly via the dashboard. If the noise comes
|
|
171
|
+
through an existing topic that the user wants quieter,
|
|
172
|
+
`mirrorExisting=false` stops it without affecting auto-create policy.
|
|
173
|
+
- **Symptom: routing latency increases.** The bridge calls are
|
|
174
|
+
fire-and-forget (`.catch(() => {})` on both `mirrorInbound` and
|
|
175
|
+
`mirrorOutbound`). Routing should not be on the critical path of any
|
|
176
|
+
Telegram call. If a regression shows otherwise, audit for an
|
|
177
|
+
unintended `await` in the relay handler.
|
|
178
|
+
- **Symptom: Telegram topic spam.** Auto-create policy gone wrong.
|
|
179
|
+
`shouldAutoCreateTopic` is unit-tested for "deny on either id" and
|
|
180
|
+
"allow on either id"; if a real spam case appears, capture the
|
|
181
|
+
`remoteAgent` + `remoteAgentName` values and add to the deny-list.
|
|
182
|
+
|
|
183
|
+
## Phase / scope
|
|
184
|
+
|
|
185
|
+
Third of five deliverables in topic-8686:
|
|
186
|
+
|
|
187
|
+
1. (a) Canonical inbox write-path — **MERGED** (#113).
|
|
188
|
+
2. (2) Settings surface — **PR #114, merging**.
|
|
189
|
+
3. **(b) Bridge module — THIS PR.**
|
|
190
|
+
4. (4) Observability tab — extends the Threadline dashboard tab to render
|
|
191
|
+
the canonical inbox + bindings + thread-resume-map.
|
|
192
|
+
5. (c) Backfill four open threads — one-shot script.
|
|
193
|
+
|
|
194
|
+
After (b) merges, the bridge is **armed but quiet by default**. The
|
|
195
|
+
user must flip `enabled=true` in the dashboard for any traffic to reach
|
|
196
|
+
Telegram. The next PR (4) lights up the observability view.
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Side-Effects Review — Threadline → Telegram Bridge: Settings Surface
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `threadline-tg-bridge-settings-surface`
|
|
4
|
+
**Date:** `2026-05-02`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `self (incident-grounded reasoning)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Ships the **settings surface** for the Threadline → Telegram bridge BEFORE
|
|
11
|
+
the bridge module itself (deliverable b) goes live. This is the second of
|
|
12
|
+
five deliverables in the topic-8686 build; it ensures default-OFF
|
|
13
|
+
auto-create is structurally enforced from day one, so when (b) lights up
|
|
14
|
+
the bridge, the user's noise budget is already wired and respected.
|
|
15
|
+
|
|
16
|
+
The settings surface is three layers:
|
|
17
|
+
|
|
18
|
+
1. **`TelegramBridgeConfig` class** — a thin, validated read/write API over
|
|
19
|
+
`LiveConfig` keys under `threadline.telegramBridge.*`. Owns the policy
|
|
20
|
+
functions `shouldAutoCreateTopic(remoteAgent)` and
|
|
21
|
+
`shouldMirrorIntoExistingTopic()` that the bridge module will call on
|
|
22
|
+
every inbound/outbound message.
|
|
23
|
+
2. **HTTP endpoints** — `GET /threadline/telegram-bridge/config` and
|
|
24
|
+
`PATCH /threadline/telegram-bridge/config`, mounted in the main route
|
|
25
|
+
set (bearer-auth enforced globally). Validation lives in the config
|
|
26
|
+
class; the route handler is a 14-line wrapper.
|
|
27
|
+
3. **Dashboard tab** — a new "Threadline" tab with a Bridge Settings card:
|
|
28
|
+
master switch, two policy toggles, and dual allow/deny-list management.
|
|
29
|
+
The same tab is the natural home for deliverable (4)'s observability
|
|
30
|
+
view; this PR ships a placeholder noting that.
|
|
31
|
+
|
|
32
|
+
Files added:
|
|
33
|
+
|
|
34
|
+
- `src/threadline/TelegramBridgeConfig.ts` — config class + `shouldAutoCreateTopic`, `shouldMirrorIntoExistingTopic` policies.
|
|
35
|
+
- `tests/unit/TelegramBridgeConfig.test.ts` — 22 unit cases.
|
|
36
|
+
- `tests/integration/telegram-bridge-config-routes.test.ts` — 8 supertest cases.
|
|
37
|
+
|
|
38
|
+
Files modified:
|
|
39
|
+
|
|
40
|
+
- `src/server/routes.ts` — `RouteContext.telegramBridgeConfig: TelegramBridgeConfig | null` + two routes.
|
|
41
|
+
- `src/server/AgentServer.ts` — accepts `options.telegramBridgeConfig`, passes through `routeCtx`.
|
|
42
|
+
- `src/commands/server.ts` — instantiates `new TelegramBridgeConfig(liveConfig)` once at boot, hands it to `AgentServer`.
|
|
43
|
+
- `dashboard/index.html` — new Threadline tab (button + panel + load/patch/render JS + tab-registry entry).
|
|
44
|
+
|
|
45
|
+
## Decision-point inventory
|
|
46
|
+
|
|
47
|
+
- `TelegramBridgeConfig.update(patch)` — **add** — partial-patch
|
|
48
|
+
application with type validation; emits `change` events per field.
|
|
49
|
+
- `TelegramBridgeConfig.shouldAutoCreateTopic(remoteAgent)` — **add** —
|
|
50
|
+
policy: `enabled && (allowList match → true; denyList match → false; else autoCreateTopics)`.
|
|
51
|
+
- `TelegramBridgeConfig.shouldMirrorIntoExistingTopic()` — **add** —
|
|
52
|
+
policy: `enabled && mirrorExisting`.
|
|
53
|
+
- `GET /threadline/telegram-bridge/config` — **add** — read endpoint
|
|
54
|
+
(bearer-auth via global `authMiddleware`).
|
|
55
|
+
- `PATCH /threadline/telegram-bridge/config` — **add** — partial-patch
|
|
56
|
+
endpoint with 400 on validation error and 503 when config not initialized.
|
|
57
|
+
- Dashboard `loadThreadlineBridgeConfig` / `tlBridgePatchConfig` — **add** —
|
|
58
|
+
load + optimistic write; rolls back via re-load on 4xx.
|
|
59
|
+
- Toggle change-handlers — **add** — bound once on `DOMContentLoaded` with
|
|
60
|
+
a `tlBridgeWiring` reentrancy guard (avoids feeding back the
|
|
61
|
+
programmatic `checked = ...` set into the change event).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 1. Over-block
|
|
66
|
+
|
|
67
|
+
**What legitimate inputs does this change reject that it shouldn't?**
|
|
68
|
+
|
|
69
|
+
The settings class deliberately rejects non-boolean toggles and non-string
|
|
70
|
+
list entries with a 400. The error messages name the offending field
|
|
71
|
+
("enabled must be boolean", "allowList must be string[]"). False positives
|
|
72
|
+
are not possible at the type level: a JSON `true`/`false` is unambiguous,
|
|
73
|
+
and a JSON array of strings is unambiguous. The dashboard cannot send
|
|
74
|
+
malformed input — `<input type="checkbox">.checked` is always a boolean
|
|
75
|
+
and the list-management code stringifies entries.
|
|
76
|
+
|
|
77
|
+
The PATCH endpoint **ignores unknown fields silently** (the route filters
|
|
78
|
+
the body to known fields before forwarding to `update`). This is
|
|
79
|
+
intentional: future toggles can be deployed server-side without breaking
|
|
80
|
+
older dashboards that don't know about them. There is a unit test for
|
|
81
|
+
this exact behaviour.
|
|
82
|
+
|
|
83
|
+
## 2. Under-block
|
|
84
|
+
|
|
85
|
+
**What failure modes does this still miss?**
|
|
86
|
+
|
|
87
|
+
- **No rate-limit on PATCH.** A pathological dashboard could thrash
|
|
88
|
+
toggles. The cost is bounded — each PATCH writes config.json
|
|
89
|
+
atomically; throughput is disk-bound, not unbounded. Acceptable for a
|
|
90
|
+
bearer-auth-gated endpoint with one user.
|
|
91
|
+
- **No audit log on config changes.** A future PR could forward the
|
|
92
|
+
`change` events from `TelegramBridgeConfig` into the existing event
|
|
93
|
+
stream, but it's out of scope for this deliverable. Today, config
|
|
94
|
+
changes show up in `config.json` git history (or backup snapshots).
|
|
95
|
+
- **The `enabled` master switch is still load-bearing for the bridge
|
|
96
|
+
module that doesn't exist yet.** This PR does NOT enforce default-OFF
|
|
97
|
+
in any code path that mirrors messages — it only persists the toggles.
|
|
98
|
+
Enforcement happens in deliverable (b), where the bridge module calls
|
|
99
|
+
`shouldAutoCreateTopic` and `shouldMirrorIntoExistingTopic` at every
|
|
100
|
+
routing decision. The unit tests for those two functions in this PR
|
|
101
|
+
pin the policy contract so (b) cannot drift.
|
|
102
|
+
- **Validation does not deduplicate trailing-whitespace in arbitrary
|
|
103
|
+
Unicode whitespace.** `dedupeAndTrim` uses `.trim()` (ASCII whitespace
|
|
104
|
+
+ Unicode whitespace per ECMAScript). Acceptable.
|
|
105
|
+
|
|
106
|
+
## 3. Level-of-abstraction fit
|
|
107
|
+
|
|
108
|
+
**Is this at the right layer?**
|
|
109
|
+
|
|
110
|
+
Yes. The split between class (validation + policy), routes (thin HTTP
|
|
111
|
+
shim), and dashboard (presentation only) is the standard
|
|
112
|
+
"signal-vs-authority" shape: brittle low-context surfaces (the dashboard
|
|
113
|
+
checkboxes) emit signals; the higher-level intelligent gate
|
|
114
|
+
(`TelegramBridgeConfig.update` + the policy functions) holds the
|
|
115
|
+
blocking authority.
|
|
116
|
+
|
|
117
|
+
The settings class lives under `src/threadline/` because it's a
|
|
118
|
+
threadline-specific feature; placing it in `src/config/` would conflate
|
|
119
|
+
it with the generic `LiveConfig`. The bridge module in deliverable (b)
|
|
120
|
+
will instantiate this class — it does NOT instantiate `LiveConfig`
|
|
121
|
+
directly, which keeps key naming centralized.
|
|
122
|
+
|
|
123
|
+
## 4. Signal-vs-authority compliance
|
|
124
|
+
|
|
125
|
+
- **Signal:** dashboard checkbox toggles, dashboard list inputs, REST
|
|
126
|
+
PATCH bodies. Each is a low-context request that "wants" something to
|
|
127
|
+
change.
|
|
128
|
+
- **Authority:** `TelegramBridgeConfig.update` is the single chokepoint
|
|
129
|
+
that validates types, dedupes lists, and writes to config.json. The
|
|
130
|
+
bridge module (b) will read its decisions through `shouldAutoCreateTopic`
|
|
131
|
+
and `shouldMirrorIntoExistingTopic` — both pure functions of the
|
|
132
|
+
current settings.
|
|
133
|
+
|
|
134
|
+
The bridge module itself, when it ships, will be **relay-only** (no
|
|
135
|
+
block/allow surface). The blocking authority for noise control lives
|
|
136
|
+
exactly here, in the config policy. This separation is the
|
|
137
|
+
signal-vs-authority memory pattern applied correctly: the bridge
|
|
138
|
+
forwards messages it sees; the config class decides what gets seen.
|
|
139
|
+
|
|
140
|
+
## 5. Interactions
|
|
141
|
+
|
|
142
|
+
- **`LiveConfig`.** All reads and writes go through the existing
|
|
143
|
+
`LiveConfig.get` / `.set` API. No new file format, no new mtime
|
|
144
|
+
watcher, no new poll. Atomic write semantics are inherited.
|
|
145
|
+
- **`config.json` schema.** The new keys `threadline.telegramBridge.*`
|
|
146
|
+
are namespaced under the existing `threadline` block. Older agents
|
|
147
|
+
without these keys read the documented defaults (defined in
|
|
148
|
+
`DEFAULT_TELEGRAM_BRIDGE_SETTINGS`). No migration needed.
|
|
149
|
+
- **Bridge module (deliverable b, future PR).** Will instantiate
|
|
150
|
+
`TelegramBridgeConfig` from `liveConfig` and call the policy functions.
|
|
151
|
+
This PR pins the contract via unit tests so (b) cannot accidentally
|
|
152
|
+
deliver while `enabled=false` or while a remote agent is in the deny
|
|
153
|
+
list.
|
|
154
|
+
- **Observability tab (deliverable 4, future PR).** Will share the same
|
|
155
|
+
Threadline dashboard tab and extend the panel HTML; the bridge
|
|
156
|
+
settings card stays put.
|
|
157
|
+
- **Bearer-auth via `authMiddleware`.** Both routes are
|
|
158
|
+
globally-authenticated. No change to auth wiring.
|
|
159
|
+
|
|
160
|
+
## 6. Rollback cost
|
|
161
|
+
|
|
162
|
+
**How easy is it to undo this if it breaks something in production?**
|
|
163
|
+
|
|
164
|
+
Trivially. The change is purely additive:
|
|
165
|
+
|
|
166
|
+
- Drop the new `TelegramBridgeConfig` class file → no callers in
|
|
167
|
+
production code (only the new server.ts instantiation + the new
|
|
168
|
+
routes use it).
|
|
169
|
+
- Drop the two routes → unauthenticated GET still 503's elsewhere; the
|
|
170
|
+
dashboard tab silently fails on `loadThreadlineBridgeConfig`.
|
|
171
|
+
- Drop the dashboard tab + JS → no regression elsewhere; other tabs
|
|
172
|
+
unaffected.
|
|
173
|
+
- The new `config.json` keys are silently ignored by older agents — no
|
|
174
|
+
schema migration to unwind.
|
|
175
|
+
|
|
176
|
+
No file format changes, no shared-state changes, no new processes, no
|
|
177
|
+
new sockets. The PR is a pure "API + UI for not-yet-shipped feature"
|
|
178
|
+
shape — the safest possible kind of change.
|
|
179
|
+
|
|
180
|
+
## Plan if a regression appears
|
|
181
|
+
|
|
182
|
+
- **Symptom: dashboard tab errors.** Check `apiFetch` logs in the browser
|
|
183
|
+
console; verify the bridge config endpoints return 200 from the agent
|
|
184
|
+
server; verify auth token is correct.
|
|
185
|
+
- **Symptom: toggle change feeds back into a loop.** The
|
|
186
|
+
`tlBridgeWiring` reentrancy guard skips the change handler while
|
|
187
|
+
`renderThreadlineBridgeConfig` is programmatically setting `.checked`.
|
|
188
|
+
If a regression escapes the guard, log the toggle source — DOM
|
|
189
|
+
`change` events are synchronous, so the guard works as long as the
|
|
190
|
+
programmatic set is followed by `tlBridgeWiring = false` in a
|
|
191
|
+
`try/finally`.
|
|
192
|
+
- **Symptom: config.json gets a stray key.** The `update` method only
|
|
193
|
+
writes the five known keys; no caller has a path to write something
|
|
194
|
+
else. If junk appears, suspect manual editing.
|
|
195
|
+
|
|
196
|
+
## Phase / scope
|
|
197
|
+
|
|
198
|
+
Second of five deliverables in topic-8686. Order:
|
|
199
|
+
|
|
200
|
+
1. (a) Canonical inbox write-path fix — **MERGED** as PR #113 (commit `9cc3e9af`).
|
|
201
|
+
2. **(2) Settings surface — THIS PR.** Default-OFF auto-create, allow/deny list, dashboard tab.
|
|
202
|
+
3. (b) Bridge module — reads this config, mirrors threadline messages.
|
|
203
|
+
4. (4) Observability tab — extends the Threadline dashboard tab.
|
|
204
|
+
5. (c) Backfill four open threads — one-shot script.
|
|
205
|
+
|
|
206
|
+
Subsequent deliverables (b, 4, c) all depend on this settings contract.
|
|
207
|
+
The 22 unit tests + 8 integration tests pin the contract so they cannot
|
|
208
|
+
drift as the bridge module is built.
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Token Ledger — bounded first-boot scan
|
|
3
|
+
slug: token-ledger-bounded-scan
|
|
4
|
+
date: 2026-05-01
|
|
5
|
+
author: echo
|
|
6
|
+
second_pass_required: false
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Summary of the change
|
|
10
|
+
|
|
11
|
+
The token ledger (shipped in v0.28.77 as Phase 1 read-only observability) does
|
|
12
|
+
a synchronous walk of `~/.claude/projects/<encoded-cwd>/<sessionId>.jsonl` on
|
|
13
|
+
every poll tick, and on first boot ingests every file it finds. On Echo's host
|
|
14
|
+
this turned out to mean **119,130 JSONL files / 12 GB of transcripts** — the
|
|
15
|
+
first scan blocked the Node event loop for minutes. The HTTP server accepted
|
|
16
|
+
TCP connections during the scan but never returned a response, including for
|
|
17
|
+
`/health`, which made the lifeline supervisor declare the agent dead and
|
|
18
|
+
restart it in a loop.
|
|
19
|
+
|
|
20
|
+
This change makes the scan bounded in three ways:
|
|
21
|
+
|
|
22
|
+
1. **Per-tick file cap (default 500)** with a persistent cursor across
|
|
23
|
+
ticks, so the ledger backfills incrementally instead of in one pass.
|
|
24
|
+
2. **Async yielding (default every 25 files)** via `setImmediate`, so even
|
|
25
|
+
within a tick the event loop gets to drain HTTP/health traffic.
|
|
26
|
+
3. **Optional max file age (default 30 days at the wiring layer)** so the
|
|
27
|
+
ledger ignores transcripts older than the backfill window. The source
|
|
28
|
+
JSONLs are unchanged and remain the ground truth — the operator can
|
|
29
|
+
widen the window later by passing a larger `maxFileAgeMs`.
|
|
30
|
+
|
|
31
|
+
A new `scanAllAsync()` method wraps the existing scan loop and is the path
|
|
32
|
+
the poller now uses. The original `scanAll()` sync method is preserved for
|
|
33
|
+
callers and tests that don't need yielding (and now honors the per-tick
|
|
34
|
+
cap and age cutoff too).
|
|
35
|
+
|
|
36
|
+
Files touched:
|
|
37
|
+
- `src/monitoring/TokenLedger.ts` — added `maxFileAgeMs`, `maxFilesPerScan`,
|
|
38
|
+
`yieldEveryNFiles` options; refactored `scanAll` into a shared
|
|
39
|
+
`scanInternal` helper plus sync (`scanAll`) and async (`scanAllAsync`)
|
|
40
|
+
entry points; added a persistent `scanCursor` for cross-tick resume.
|
|
41
|
+
- `src/monitoring/TokenLedgerPoller.ts` — switched `tick()` to await
|
|
42
|
+
`scanAllAsync()` (still fire-and-forget; reentry guard unchanged).
|
|
43
|
+
- `src/server/AgentServer.ts` — wires the three caps with sensible defaults
|
|
44
|
+
(30-day age window, 500 files/tick, yield every 25 files).
|
|
45
|
+
- `tests/unit/token-ledger.test.ts` — 3 new tests for cursor resume,
|
|
46
|
+
age cutoff, and async yielding behavior.
|
|
47
|
+
|
|
48
|
+
The change has no decision-point surface. The ledger is still pure
|
|
49
|
+
observability: never gates, blocks, filters, or alters any agent behavior.
|
|
50
|
+
Adding caps does mean the data picture is incomplete during early backfill,
|
|
51
|
+
but only the *speed of completeness* changes — not whether the data ever
|
|
52
|
+
becomes complete.
|
|
53
|
+
|
|
54
|
+
## Decision-point inventory
|
|
55
|
+
|
|
56
|
+
The change has no block/allow/route surface. There is no dispatcher,
|
|
57
|
+
sentinel, gate, or watchdog being added or modified. The "orphans" view
|
|
58
|
+
remains a signal-only list (no kill authority), unchanged.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 1. Over-block
|
|
63
|
+
|
|
64
|
+
No block/allow surface — over-block not applicable.
|
|
65
|
+
|
|
66
|
+
The closest analogue would be "the dashboard hides data that does exist on
|
|
67
|
+
disk." That's a property of the new caps: a 90-day-old session won't appear
|
|
68
|
+
in `/tokens/summary` until the operator widens `maxFileAgeMs`. This is
|
|
69
|
+
visibility-shaping, not authority. No automation reads
|
|
70
|
+
`/tokens/summary` and acts on it.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 2. Under-block
|
|
75
|
+
|
|
76
|
+
No block/allow surface — under-block not applicable.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 3. Level-of-abstraction fit
|
|
81
|
+
|
|
82
|
+
The fix lives entirely inside the existing `src/monitoring/TokenLedger.ts`
|
|
83
|
+
file and its poller. It does not introduce a new framework, queue, or
|
|
84
|
+
abstraction. The caps are normal constructor options on the same class
|
|
85
|
+
that already exists. The cursor is a private instance field. The async
|
|
86
|
+
variant uses `setImmediate` — the standard Node primitive for yielding
|
|
87
|
+
to the event loop, which is what every other long-running scanner in this
|
|
88
|
+
codebase uses (see `OrphanProcessReaper`, `MemoryPressureMonitor`).
|
|
89
|
+
|
|
90
|
+
The wiring change in `AgentServer.ts` is co-located with the original
|
|
91
|
+
ledger initialization that landed in v0.28.77 — same try/catch,
|
|
92
|
+
same null-on-failure behavior.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 4. Signal vs authority compliance
|
|
97
|
+
|
|
98
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
99
|
+
|
|
100
|
+
- [x] No — this change has no block/allow surface.
|
|
101
|
+
|
|
102
|
+
The ledger remains pure read-side observability. The bounding logic does
|
|
103
|
+
not gain any authority — it only changes the cadence at which data
|
|
104
|
+
becomes visible. Future kill-orphan automation, budget enforcement, or
|
|
105
|
+
compaction triggers remain explicitly out of scope and would be separate
|
|
106
|
+
changes with their own review (per the principle, those would feed an
|
|
107
|
+
LLM-backed authority, not become their own brittle blockers).
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 5. Interactions
|
|
112
|
+
|
|
113
|
+
- **Shadowing:** None. No new route, no new file path, no new dispatcher.
|
|
114
|
+
The ledger DB schema is unchanged (no migration needed).
|
|
115
|
+
- **Double-fire:** None. The poller's `running` reentry guard is unchanged
|
|
116
|
+
and still skips a tick if the previous one is in flight. Cursor state
|
|
117
|
+
is mutated only inside the (single-threaded) scan loop; no cross-tick
|
|
118
|
+
race because reentry is blocked.
|
|
119
|
+
- **Races:** Cursor invalidation is handled — if `projectDirs` shrinks
|
|
120
|
+
between ticks (a project directory was deleted), the cursor is reset to
|
|
121
|
+
`{0, 0}` rather than indexing past the end. The `INSERT OR IGNORE` on
|
|
122
|
+
`request_id` continues to make ingest idempotent regardless of cursor
|
|
123
|
+
re-traversal.
|
|
124
|
+
- **Feedback loops:** None. The caps don't create any new path back into
|
|
125
|
+
Claude Code or the agent's behavior. The ledger continues to be
|
|
126
|
+
downstream of Claude Code's logging.
|
|
127
|
+
- **Cross-restart:** The cursor resets on process restart (it's an
|
|
128
|
+
instance field, not persisted). This is correct: after a restart, the
|
|
129
|
+
ledger DB itself records which files have been read up to which offset
|
|
130
|
+
(`file_offsets` table), so re-scanning previously-ingested files is
|
|
131
|
+
cheap (the offset check fires before any line parsing). The cursor
|
|
132
|
+
exists only to bound *intra-process* work; per-file resume is already
|
|
133
|
+
handled by the durable offset table from v0.28.77.
|
|
134
|
+
|
|
135
|
+
One subtle interaction worth naming: the `maxFileAgeMs` filter uses
|
|
136
|
+
`fs.statSync(fp).mtimeMs`. If a JSONL is *appended to* (Claude Code adds
|
|
137
|
+
a turn to an existing session), the mtime updates and the file becomes
|
|
138
|
+
in-window again — so active sessions never get blackholed by the age cap.
|
|
139
|
+
Only sessions that are truly dormant past the cap drop out of the rotation.
|
|
140
|
+
Verified by test: the `respects maxFileAgeMs` test backdates a file with
|
|
141
|
+
`fs.utimesSync` to confirm the filter triggers on stale mtime.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 6. External surfaces
|
|
146
|
+
|
|
147
|
+
- **Other agents on the same machine:** No effect on their behavior. They
|
|
148
|
+
each gain the bounded-scan defaults when they upgrade.
|
|
149
|
+
- **Other users of the install base:** Pure additive option surface. Old
|
|
150
|
+
callers passing only `dbPath` and `claudeProjectsDir` get the new
|
|
151
|
+
defaults automatically. No existing API contract changed.
|
|
152
|
+
- **External systems:** None. No new outbound calls.
|
|
153
|
+
- **Persistent state:** No schema migration. The existing `file_offsets`
|
|
154
|
+
table continues to drive per-file resume. The new cursor is in-memory
|
|
155
|
+
only.
|
|
156
|
+
- **Timing/runtime:** First-boot scan now spans many ticks instead of
|
|
157
|
+
blocking the event loop. On Echo's box (119k files, mostly stale): with
|
|
158
|
+
defaults, the first useful tick reads ~500 files within a 30-day window,
|
|
159
|
+
yielding every 25 files; subsequent ticks pick up the cursor. Steady
|
|
160
|
+
state once backfill is done is identical to v0.28.77 (same offset-check
|
|
161
|
+
no-op for already-ingested files).
|
|
162
|
+
|
|
163
|
+
The reader remains **strictly read-only against `~/.claude/projects/`**.
|
|
164
|
+
No write fds are ever opened.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 7. Rollback cost
|
|
169
|
+
|
|
170
|
+
Pure additive change. Rollback steps:
|
|
171
|
+
|
|
172
|
+
1. Revert the commit. Ship as next patch release.
|
|
173
|
+
2. The ledger DB at `<stateDir>/server-data/token-ledger.db` is unchanged
|
|
174
|
+
on disk (no schema migration). Reverting goes back to unbounded scan
|
|
175
|
+
behavior — which is broken on agents with deep history, so we'd want
|
|
176
|
+
to either (a) deploy a different fix, or (b) ship a config option that
|
|
177
|
+
defaults the agent to NOT initialize the ledger at all on the affected
|
|
178
|
+
hosts. But the DB itself is fine.
|
|
179
|
+
3. No agent state repair needed.
|
|
180
|
+
|
|
181
|
+
Estimated rollback time: minutes. Pure code revert.
|
|
182
|
+
|
|
183
|
+
If the bounded defaults turn out to be wrong (too aggressive), the operator
|
|
184
|
+
can override per-agent via the AgentServer construction call (or, if a
|
|
185
|
+
config knob is added later, via `.instar/config.json`). No re-deploy needed
|
|
186
|
+
to widen the window — the data is still in `~/.claude/projects/`.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Conclusion
|
|
191
|
+
|
|
192
|
+
This change is a containment fix for a v0.28.77 regression: the ledger
|
|
193
|
+
shipped without considering agents that have years of accumulated Claude
|
|
194
|
+
Code history, and the unbounded synchronous first scan blocked the
|
|
195
|
+
server's event loop. The fix bounds work via three independent
|
|
196
|
+
mechanisms (per-tick file cap, intra-tick yielding, age cutoff) so that
|
|
197
|
+
no plausible JSONL tree can stall the agent. None of these mechanisms
|
|
198
|
+
introduce decision-point surface or change the ledger's read-only,
|
|
199
|
+
observability-only character.
|
|
200
|
+
|
|
201
|
+
The change is clear to ship.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Second-pass review (if required)
|
|
206
|
+
|
|
207
|
+
Not required. The change does not touch any of the trigger criteria from
|
|
208
|
+
the side-effects-review skill (block/allow on messaging or dispatch,
|
|
209
|
+
session lifecycle, context exhaustion/compaction, coherence/idempotency/
|
|
210
|
+
trust, sentinel/guard/gate/watchdog).
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Evidence pointers
|
|
215
|
+
|
|
216
|
+
- Reproduction (before fix): start v0.28.77 server on a host with deep
|
|
217
|
+
Claude Code history. `curl http://localhost:4042/health` hangs;
|
|
218
|
+
`sample <pid> 1` shows the main thread spending 100% of its time in
|
|
219
|
+
`uv_fs_stat` callbacks under `Builtins_InterpreterEntryTrampoline`
|
|
220
|
+
(i.e., a JS loop hammering the filesystem). The lifeline supervisor
|
|
221
|
+
declares the server unhealthy and restarts it in a loop.
|
|
222
|
+
- Reproduction (after fix): same host, same `~/.claude/projects/` tree.
|
|
223
|
+
`curl http://localhost:4042/health` returns within a few hundred ms
|
|
224
|
+
immediately on boot. `curl /tokens/summary` returns valid JSON
|
|
225
|
+
(initially with a small subset of recent sessions; backfill fills in
|
|
226
|
+
across subsequent ticks).
|
|
227
|
+
- Unit tests: `tests/unit/token-ledger.test.ts` — 15/15 passing locally
|
|
228
|
+
on `fix/token-ledger-bounded-scan` branch. New tests cover the three
|
|
229
|
+
bounding mechanisms (cursor resume, age cutoff, async yielding).
|
|
230
|
+
- Typecheck: `npx tsc --noEmit` clean.
|