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,203 @@
|
|
|
1
|
+
# Side-Effects Review — Threadline Bridge Backfill Script
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `threadline-bridge-backfill`
|
|
4
|
+
**Date:** `2026-05-02`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `self (incident-grounded reasoning)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Final deliverable in topic-8686. Ships a one-shot CLI script that
|
|
11
|
+
backfills threadline-message history into Telegram topics using the
|
|
12
|
+
bridge primitives from PR #117 — so the user has a complete picture of
|
|
13
|
+
agent-to-agent traffic, including conversations that landed BEFORE the
|
|
14
|
+
bridge shipped.
|
|
15
|
+
|
|
16
|
+
Files added:
|
|
17
|
+
|
|
18
|
+
- `scripts/threadline-bridge-backfill.mjs` — the CLI script. Reads the
|
|
19
|
+
agent's canonical inbox/outbox files (PR #113, PR #118), an optional
|
|
20
|
+
seed file of historically-reconstructed messages, and the existing
|
|
21
|
+
bridge bindings. Creates Telegram topics with the bridge naming
|
|
22
|
+
pattern, posts a backfill banner explaining what the user is seeing,
|
|
23
|
+
then posts each message chronologically with chunking under 4000 chars.
|
|
24
|
+
Idempotent via a per-thread ledger at
|
|
25
|
+
`.instar/threadline/bridge-backfill-ledger.json`.
|
|
26
|
+
- `src/threadline/BackfillCore.ts` — pure helpers (`buildTopicName`,
|
|
27
|
+
`chunkBody`, `groupByThread`, `pickCounterparty`, `ledgerKey`,
|
|
28
|
+
`formatBackfillMessage`). Source of truth for the contract; the
|
|
29
|
+
script's inline copies must stay in sync.
|
|
30
|
+
- `tests/unit/BackfillCore.test.ts` — 16 unit cases pinning the contract.
|
|
31
|
+
|
|
32
|
+
Files modified: none (this PR is pure additions on top of the four
|
|
33
|
+
prior PRs in the topic-8686 set).
|
|
34
|
+
|
|
35
|
+
## Decision-point inventory
|
|
36
|
+
|
|
37
|
+
- `scripts/threadline-bridge-backfill.mjs` — **add** — CLI with
|
|
38
|
+
`--state-dir`, `--port`, `--threads`, `--seed`, `--dry-run`,
|
|
39
|
+
`--no-create` flags. Calls `POST /telegram/topics` to create and
|
|
40
|
+
`POST /telegram/post-update` to post.
|
|
41
|
+
- `BackfillCore.buildTopicName` — **add** — same shape and limits as
|
|
42
|
+
`TelegramBridge.buildTopicName` from PR #117.
|
|
43
|
+
- `BackfillCore.chunkBody` — **add** — fixed 3800-char chunks with no
|
|
44
|
+
word-boundary alignment (Telegram preserves whitespace; visual
|
|
45
|
+
continuity is acceptable).
|
|
46
|
+
- `BackfillCore.groupByThread` — **add** — combines inbox + outbox +
|
|
47
|
+
seed; sorts each thread chronologically.
|
|
48
|
+
- `BackfillCore.formatBackfillMessage` — **add** — emoji prefix
|
|
49
|
+
(📥 / 📤), counterparty name, ISO timestamp, body.
|
|
50
|
+
- Backfill ledger format — **add** — `{ version: 1, threads: { [threadId]: { topicId, topicName, posted: [...], lastBackfillAt } } }`.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 1. Over-block
|
|
55
|
+
|
|
56
|
+
**What legitimate inputs does this change reject that it shouldn't?**
|
|
57
|
+
|
|
58
|
+
The script is purely additive and doesn't gate any existing flows.
|
|
59
|
+
Validation:
|
|
60
|
+
|
|
61
|
+
- Empty / unparseable seed file → warn + treat as `[]`.
|
|
62
|
+
- Thread with no on-disk or seed messages → warn + skip.
|
|
63
|
+
- `--no-create` + no existing binding → warn + skip (the user explicitly
|
|
64
|
+
asked NOT to create topics).
|
|
65
|
+
- `--dry-run` → prints the plan without making any HTTP calls.
|
|
66
|
+
|
|
67
|
+
No false-positive rejects. The `--threads` filter is exact-match on
|
|
68
|
+
threadId; that's intentional — partial matching here would be a
|
|
69
|
+
foot-gun (accidentally backfilling more threads than intended).
|
|
70
|
+
|
|
71
|
+
## 2. Under-block
|
|
72
|
+
|
|
73
|
+
**What failure modes does this still miss?**
|
|
74
|
+
|
|
75
|
+
- **Orphan topics on partial-success.** If topic creation succeeds but
|
|
76
|
+
the first message post fails, we have a Telegram topic with only the
|
|
77
|
+
banner. Acceptable — the ledger records the topic id; a re-run
|
|
78
|
+
picks up where it left off and posts the remaining messages.
|
|
79
|
+
- **Order-of-arrival sensitivity for the first run.** If two backfill
|
|
80
|
+
invocations race, both could create a topic for the same thread.
|
|
81
|
+
Mitigation: the ledger write is the second step (after creation); a
|
|
82
|
+
duplicate would be detectable and could be removed manually. This
|
|
83
|
+
script is one-shot, intended to be run by Justin on demand, not
|
|
84
|
+
scheduled — the race window is hypothetical.
|
|
85
|
+
- **No HMAC verification of inbox/outbox lines.** The script trusts
|
|
86
|
+
the JSONL files. Same posture as the observability layer in PR #118:
|
|
87
|
+
the HMAC is for tamper-evidence at write time; reading for
|
|
88
|
+
user-visible mirroring doesn't need to re-verify (no decision
|
|
89
|
+
surface). If a tampered line surfaces in Telegram, the user sees
|
|
90
|
+
it in the conversation view and can investigate.
|
|
91
|
+
- **No quota-aware throttling beyond a 250ms gap.** Telegram's
|
|
92
|
+
default rate limit is ~30 messages/second to the same chat;
|
|
93
|
+
4 messages/second is well below. If a thread has 1000+ messages
|
|
94
|
+
this still completes in ~4 minutes, which is acceptable for a
|
|
95
|
+
one-shot.
|
|
96
|
+
|
|
97
|
+
## 3. Level-of-abstraction fit
|
|
98
|
+
|
|
99
|
+
The script is a CLI wrapper over the agent's existing
|
|
100
|
+
`/telegram/topics` and `/telegram/post-update` HTTP routes. It
|
|
101
|
+
deliberately does NOT:
|
|
102
|
+
|
|
103
|
+
- Instantiate `TelegramAdapter` directly — would duplicate the agent
|
|
104
|
+
server's connection state.
|
|
105
|
+
- Call `TelegramBridge.mirrorInbound` — the bridge writes its own
|
|
106
|
+
bindings file; the script reuses that file. We don't go through the
|
|
107
|
+
bridge because the bridge would consult `TelegramBridgeConfig`
|
|
108
|
+
(default-OFF) and refuse to post; the script's purpose is to
|
|
109
|
+
backfill regardless of the live policy.
|
|
110
|
+
- Touch the canonical inbox/outbox files — those are append-only
|
|
111
|
+
signals from the live agent; the script reads them but never
|
|
112
|
+
rewrites them.
|
|
113
|
+
|
|
114
|
+
Putting the pure helpers in `src/threadline/BackfillCore.ts` keeps
|
|
115
|
+
them tsc-checked and unit-tested while letting the script stay a
|
|
116
|
+
plain `.mjs` (no build step required to run).
|
|
117
|
+
|
|
118
|
+
## 4. Signal-vs-authority compliance
|
|
119
|
+
|
|
120
|
+
- **Signal:** the on-disk inbox/outbox files; the optional seed file.
|
|
121
|
+
- **Authority:** none. The script has no decision surface on the
|
|
122
|
+
routing path — it doesn't gate or alter any threadline flow. The
|
|
123
|
+
Telegram topic creation goes through the existing `/telegram/topics`
|
|
124
|
+
route, which is the authority for forum-topic creation.
|
|
125
|
+
|
|
126
|
+
The script intentionally **bypasses** `TelegramBridgeConfig` because
|
|
127
|
+
backfill is an explicit user action. The user already opted in by
|
|
128
|
+
running the script with the relevant `--threads` argument; consulting
|
|
129
|
+
the dashboard toggle would re-derive that consent. The script's
|
|
130
|
+
output is fully auditable in the ledger.
|
|
131
|
+
|
|
132
|
+
## 5. Interactions
|
|
133
|
+
|
|
134
|
+
- **PR #113 (canonical inbox).** Reads `inbox.jsonl.active`. No write.
|
|
135
|
+
- **PR #117 (bridge module).** Reads `telegram-bridge-bindings.json`.
|
|
136
|
+
Reuses existing bindings (no new bridge-side artifact unless the
|
|
137
|
+
script creates a topic, in which case the next live `mirrorInbound`
|
|
138
|
+
/ `mirrorOutbound` call will see the binding via the bindings file
|
|
139
|
+
the script writes — wait, NO: this script does NOT write to
|
|
140
|
+
`telegram-bridge-bindings.json`. It writes only to its own ledger.
|
|
141
|
+
This means the live bridge has no awareness of script-created
|
|
142
|
+
topics until a new bridge-driven message comes through, at which
|
|
143
|
+
point `findOrCreateForumTopic` returns the existing topic id and
|
|
144
|
+
the bridge writes its own binding. This is desirable: the bridge
|
|
145
|
+
remains the only writer of `telegram-bridge-bindings.json`,
|
|
146
|
+
preserving single-writer simplicity.
|
|
147
|
+
- **PR #118 (observability tab).** Reads `outbox.jsonl.active` (which
|
|
148
|
+
PR #118 now writes). No write.
|
|
149
|
+
- **`/telegram/topics` route.** Existing route, unchanged.
|
|
150
|
+
- **`/telegram/post-update` route.** Existing route, unchanged.
|
|
151
|
+
- **Backfill ledger.** New file at
|
|
152
|
+
`.instar/threadline/bridge-backfill-ledger.json` — the script is the
|
|
153
|
+
only writer. Format is versioned (`version: 1`) so future format
|
|
154
|
+
changes can land without breaking older ledgers.
|
|
155
|
+
|
|
156
|
+
## 6. Rollback cost
|
|
157
|
+
|
|
158
|
+
- The script is a CLI; not running it is the rollback. No recurring
|
|
159
|
+
process, no background job, no config flag.
|
|
160
|
+
- If a bad backfill posted unwanted content to Telegram, the user
|
|
161
|
+
deletes the topic via the Telegram UI. The script's ledger entry
|
|
162
|
+
for that thread can be removed manually (`rm` the
|
|
163
|
+
`bridge-backfill-ledger.json` entry), and a re-run with
|
|
164
|
+
`--no-create` will skip the deleted thread.
|
|
165
|
+
- `BackfillCore.ts` is unused outside the test file (the script
|
|
166
|
+
duplicates the logic inline) — drop the file with no import
|
|
167
|
+
consequences.
|
|
168
|
+
|
|
169
|
+
## Plan if a regression appears
|
|
170
|
+
|
|
171
|
+
- **Symptom: script creates duplicate topics.** Check the ledger;
|
|
172
|
+
ensure the thread's `topicId` field is populated. If null, the
|
|
173
|
+
topic-creation HTTP call must have failed mid-flight; re-running
|
|
174
|
+
is safe (the `bindings` lookup will find the orphan binding from
|
|
175
|
+
the previous run via the agent's bridge if it ran since). If
|
|
176
|
+
duplicates persist, delete one in Telegram and remove its ledger
|
|
177
|
+
entry.
|
|
178
|
+
- **Symptom: messages posted in wrong order.** The grouping step
|
|
179
|
+
sorts by ISO timestamp. If timestamps are missing or non-ISO,
|
|
180
|
+
inbound/outbound order can drift. Check the seed file for
|
|
181
|
+
timestamp consistency.
|
|
182
|
+
- **Symptom: rate-limited by Telegram.** Increase the `SEND_GAP_MS`
|
|
183
|
+
constant or add `--gap <ms>` flag. Documented in the script header.
|
|
184
|
+
|
|
185
|
+
## Phase / scope
|
|
186
|
+
|
|
187
|
+
Final of five deliverables in topic-8686. Closes the build:
|
|
188
|
+
|
|
189
|
+
1. (a) Canonical inbox write-path — **MERGED** (#113).
|
|
190
|
+
2. (2) Settings surface — **MERGED** (#114).
|
|
191
|
+
3. (b) Bridge module — **MERGED** (#117).
|
|
192
|
+
4. (4) Observability tab — **PR open** (#118).
|
|
193
|
+
5. **(c) Backfill script — THIS PR.**
|
|
194
|
+
|
|
195
|
+
After this PR ships, Justin can use the dashboard's Threadline tab to
|
|
196
|
+
see live agent-to-agent traffic in real time (post-bridge-enable),
|
|
197
|
+
and run the backfill script to populate Telegram with any historical
|
|
198
|
+
threads he wants visible. The four specific threads named in the
|
|
199
|
+
topic-8686 brief (worktree-audit handoff, Dawn first handoff, Dawn
|
|
200
|
+
four-spawn thread, GROUND-TRUTH round-trip) can be backfilled by
|
|
201
|
+
running the script with a `--seed` file containing the reconstructed
|
|
202
|
+
historical messages — the script handles topic creation, banner,
|
|
203
|
+
chunking, and idempotency.
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Side-Effects Review — Threadline Canonical Inbox Write at Relay-Ingest
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `threadline-canonical-inbox-write`
|
|
4
|
+
**Date:** `2026-05-02`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `self (incident-grounded reasoning)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
The threadline relay handler in `src/commands/server.ts` (`gate-passed`
|
|
11
|
+
event listener) had three routing branches — pipe-mode (`PipeSessionSpawner`),
|
|
12
|
+
warm-listener (`ListenerSessionManager.writeToInbox`), and cold-spawn
|
|
13
|
+
(`ThreadlineRouter.handleInboundMessage`). Only the warm-listener branch
|
|
14
|
+
wrote to a per-rotation queue file (`state/listener-inbox-{rotation}.jsonl`);
|
|
15
|
+
none of the three branches wrote to the **canonical** threadline inbox at
|
|
16
|
+
`.instar/threadline/inbox.jsonl.active`. As a result the canonical inbox
|
|
17
|
+
file was frozen since 2026-04-05, hiding ~4 weeks of inbound traffic from
|
|
18
|
+
the dashboard, observability, and any consumer that reads the canonical
|
|
19
|
+
file (e.g. the planned threadline → telegram bridge).
|
|
20
|
+
|
|
21
|
+
This change adds a single canonical-inbox append at relay-ingest, BEFORE
|
|
22
|
+
the pipe / listener / cold-spawn branching, so all three paths agree on
|
|
23
|
+
one source of truth. The hoist runs through a new
|
|
24
|
+
`ListenerSessionManager.appendCanonicalInboxEntry()` helper that writes
|
|
25
|
+
HMAC-signed entries to `threadline/inbox.jsonl.active` using the same
|
|
26
|
+
HKDF-derived signing key the daemon and warm-listener already share —
|
|
27
|
+
no key divergence, no ambient-key footgun.
|
|
28
|
+
|
|
29
|
+
Files modified:
|
|
30
|
+
|
|
31
|
+
- `src/threadline/ListenerSessionManager.ts` — adds
|
|
32
|
+
`canonicalInboxPath` getter and `appendCanonicalInboxEntry(opts)` method.
|
|
33
|
+
The new method writes to the canonical inbox path; it does NOT write
|
|
34
|
+
the wake sentinel (the warm-listener queue and its sentinel remain a
|
|
35
|
+
separate, listener-only concern).
|
|
36
|
+
- `src/commands/server.ts` — in the `gate-passed` event handler, after
|
|
37
|
+
auto-ack and BEFORE the pipe / listener / cold-spawn branching, calls
|
|
38
|
+
`listenerManager.appendCanonicalInboxEntry({ ... })` once. Wrapped in
|
|
39
|
+
try/catch with a non-fatal warn — routing continues even if the
|
|
40
|
+
canonical append fails, preserving message liveness over auditability.
|
|
41
|
+
|
|
42
|
+
Tests added: 6 new unit cases in
|
|
43
|
+
`tests/unit/ListenerSessionManager.test.ts > canonical inbox`:
|
|
44
|
+
|
|
45
|
+
1. `canonicalInboxPath` getter returns `threadline/inbox.jsonl.active`
|
|
46
|
+
2. `appendCanonicalInboxEntry` creates the directory on first write and
|
|
47
|
+
appends a parseable JSON line with the right fields
|
|
48
|
+
3. The HMAC of a canonical entry round-trips through the existing
|
|
49
|
+
`verifyEntry()` — proves daemon/listener/relay share one signing key
|
|
50
|
+
4. Multiple appends produce multiple lines in chronological order
|
|
51
|
+
5. An optional caller-supplied `messageId` is honored as the entry id
|
|
52
|
+
6. The canonical inbox file is created with `0o600` permissions
|
|
53
|
+
|
|
54
|
+
Local result: 45/46 pass; the 1 failing case
|
|
55
|
+
(`state management > starts in dead state`) is a pre-existing failure
|
|
56
|
+
documented in prior `instar-dev` traces (e.g.
|
|
57
|
+
`2026-04-27T15-50-00Z-telegram-delivery-robustness-layer-3.json`) and
|
|
58
|
+
unrelated to this change.
|
|
59
|
+
|
|
60
|
+
## Decision-point inventory
|
|
61
|
+
|
|
62
|
+
- `ListenerSessionManager.appendCanonicalInboxEntry` — **add** — pure
|
|
63
|
+
canonical-inbox append, no wake sentinel.
|
|
64
|
+
- `ListenerSessionManager.canonicalInboxPath` — **add** — getter for the
|
|
65
|
+
canonical inbox path, kept side-by-side with `inboxPath` (warm-listener
|
|
66
|
+
queue) so the two roles are visibly distinct in the API surface.
|
|
67
|
+
- `gate-passed` handler in `server.ts` — **modify** — runs canonical
|
|
68
|
+
append once, before any branching. No change to pipe-mode, warm-listener,
|
|
69
|
+
or cold-spawn routing decisions or behavior.
|
|
70
|
+
- HMAC key — **pass-through** — the new helper uses the same HKDF-derived
|
|
71
|
+
signing key (`info: 'instar-inbox-signing'`) that
|
|
72
|
+
`writeToInbox` and the listener daemon already use; no new key, no new
|
|
73
|
+
derivation parameter.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 1. Over-block
|
|
78
|
+
|
|
79
|
+
**What legitimate inputs does this change reject that it shouldn't?**
|
|
80
|
+
|
|
81
|
+
None. The hoist is a relay (write-only), not a gate. It does not block,
|
|
82
|
+
delay, or filter messages. Routing decisions — pipe vs warm vs cold-spawn —
|
|
83
|
+
are unchanged. Auto-ack timing is unchanged. The canonical write happens
|
|
84
|
+
synchronously in the same event handler, on the same Node.js event loop,
|
|
85
|
+
adding a single `appendFileSync` call — no I/O contention with the routing
|
|
86
|
+
branches that follow.
|
|
87
|
+
|
|
88
|
+
The append is wrapped in try/catch with a non-fatal warning. If the
|
|
89
|
+
canonical write fails (disk full, permission error, etc.), the message
|
|
90
|
+
still routes through pipe / listener / cold-spawn as it does today.
|
|
91
|
+
Liveness is preserved over auditability when those two are in tension.
|
|
92
|
+
|
|
93
|
+
## 2. Under-block
|
|
94
|
+
|
|
95
|
+
**What failure modes does this still miss?**
|
|
96
|
+
|
|
97
|
+
- **Failure-open on canonical-inbox write.** A disk error during
|
|
98
|
+
`appendFileSync` produces a single warn line and the message routes
|
|
99
|
+
normally. The canonical inbox loses that entry. Acceptable: the same
|
|
100
|
+
behavior is already in place for the warm-listener `writeToInbox` and
|
|
101
|
+
for the daemon's `writeInboxEntry` — none of them block routing on
|
|
102
|
+
inbox-write failure. The canonical inbox is an audit / observability
|
|
103
|
+
surface, not a gate.
|
|
104
|
+
- **Pre-existing freeze (Apr 5 → May 1).** Backfilling the missing
|
|
105
|
+
~4 weeks of inbound messages is OUT OF SCOPE for this PR — that's
|
|
106
|
+
deliverable (c) in the topic-8686 build (separate PR, separate review).
|
|
107
|
+
This PR fixes the write-path going forward; (c) reconstructs the
|
|
108
|
+
history from spawn-session transcripts and the thread-resume map.
|
|
109
|
+
- **Listener daemon path (`listener-daemon.ts`) still bypasses this code
|
|
110
|
+
path.** The daemon connects to the relay independently and has its own
|
|
111
|
+
`writeInboxEntry` that already targets the canonical file. This PR
|
|
112
|
+
does NOT alter the daemon. When the daemon is the active relay
|
|
113
|
+
consumer, it continues to write canonically as it does today; when the
|
|
114
|
+
in-process relay client (server.ts handler) is the consumer, the new
|
|
115
|
+
hoist takes care of canonical writes. Both paths converge on the same
|
|
116
|
+
file with the same HMAC key.
|
|
117
|
+
|
|
118
|
+
## 3. Level-of-abstraction fit
|
|
119
|
+
|
|
120
|
+
**Is this at the right layer?**
|
|
121
|
+
|
|
122
|
+
Yes. The relay handler is the natural choke point: it is the single
|
|
123
|
+
function in the in-process relay consumer that sees every inbound
|
|
124
|
+
message exactly once before any routing decision. Doing the canonical
|
|
125
|
+
write here — rather than inside each routing branch — is the
|
|
126
|
+
single-source-of-truth pattern the spec calls for.
|
|
127
|
+
|
|
128
|
+
The helper lives on `ListenerSessionManager` because that class already
|
|
129
|
+
owns the HMAC key derivation and the existing `writeToInbox` + `verifyEntry`
|
|
130
|
+
methods. Adding a sibling method that targets the canonical path keeps
|
|
131
|
+
the key derivation, HMAC computation, and entry shape in one place.
|
|
132
|
+
A future refactor could extract a separate `CanonicalInboxWriter` class,
|
|
133
|
+
but the cost-of-now (one new method, ~30 LoC, one new getter) is lower
|
|
134
|
+
than the cost-of-extraction (new class, dependency wiring, test scaffolding).
|
|
135
|
+
|
|
136
|
+
## 4. Signal-vs-authority compliance
|
|
137
|
+
|
|
138
|
+
**Where is the signal? Where is the authority?**
|
|
139
|
+
|
|
140
|
+
- **Signal:** the inbound `gate-passed` event itself, which has already
|
|
141
|
+
been authorized by `InboundMessageGate`. The canonical append is a
|
|
142
|
+
pure observation of that signal — write-once, append-only, no decision
|
|
143
|
+
surface.
|
|
144
|
+
- **Authority:** unchanged. The pipe / warm-listener / cold-spawn
|
|
145
|
+
routing decision still lives in `server.ts` (and downstream in
|
|
146
|
+
`PipeSessionSpawner.shouldUsePipeMode`, `ListenerSessionManager.shouldUseListener`,
|
|
147
|
+
`ThreadlineRouter.handleInboundMessage`). The canonical inbox does not
|
|
148
|
+
gate, throttle, or veto routing.
|
|
149
|
+
|
|
150
|
+
The split passes the signal-vs-authority memory test: a brittle/low-context
|
|
151
|
+
write path (the canonical append) emits a signal; the higher-level
|
|
152
|
+
intelligent gate (already-existing `InboundMessageGate` upstream of the
|
|
153
|
+
`gate-passed` event) holds the blocking authority.
|
|
154
|
+
|
|
155
|
+
## 5. Interactions
|
|
156
|
+
|
|
157
|
+
**What other systems does this touch?**
|
|
158
|
+
|
|
159
|
+
- **Warm-listener queue (`state/listener-inbox-{rotation}.jsonl`).** No
|
|
160
|
+
change. The warm-listener path still calls `writeToInbox` which writes
|
|
161
|
+
to the rotated per-listener file AND the wake sentinel. Both files
|
|
162
|
+
coexist: canonical = audit/observability/bridge source; rotated =
|
|
163
|
+
warm-listener queue.
|
|
164
|
+
- **Listener daemon (`listener-daemon.ts`).** No change. The daemon's
|
|
165
|
+
`writeInboxEntry` already targets the canonical file. After this PR,
|
|
166
|
+
there are exactly two writers to the canonical file — the daemon (for
|
|
167
|
+
the standalone-listener mode) and the in-process relay handler (for
|
|
168
|
+
the in-server mode). They are mutually exclusive at runtime: only one
|
|
169
|
+
is the active relay consumer at a time.
|
|
170
|
+
- **Threadline → Telegram bridge (deliverable b, future PR).** This PR
|
|
171
|
+
is a precondition. The bridge reads the canonical inbox to know which
|
|
172
|
+
messages to mirror into Telegram; without this fix, the bridge would
|
|
173
|
+
see no traffic on the cold-spawn or pipe paths. After this PR the
|
|
174
|
+
bridge has a complete signal stream.
|
|
175
|
+
- **Dashboard observability tab (deliverable 4, future PR).** Same: the
|
|
176
|
+
observability tab reads the canonical inbox and the thread-resume map.
|
|
177
|
+
This PR ensures the canonical inbox is actually populated.
|
|
178
|
+
|
|
179
|
+
## 6. Rollback cost
|
|
180
|
+
|
|
181
|
+
**How easy is it to undo this if it breaks something in production?**
|
|
182
|
+
|
|
183
|
+
Trivially easy. The change is two surgical additions:
|
|
184
|
+
|
|
185
|
+
1. A new method + getter on `ListenerSessionManager` (no callers in
|
|
186
|
+
tests or production reference it except the new test file and the
|
|
187
|
+
new `server.ts` call site).
|
|
188
|
+
2. A 13-line block in `server.ts` that is fully wrapped in `if (listenerManager)`
|
|
189
|
+
and `try/catch`. Removing that block restores the prior behavior
|
|
190
|
+
exactly.
|
|
191
|
+
|
|
192
|
+
No schema migrations, no new file format, no new key material, no
|
|
193
|
+
dashboard changes. The canonical inbox file is append-only JSONL — if a
|
|
194
|
+
subsequent change wants to drop the entries, `rm` the file (or rotate
|
|
195
|
+
it). No referential integrity to unwind.
|
|
196
|
+
|
|
197
|
+
## Plan if a regression appears
|
|
198
|
+
|
|
199
|
+
- **Symptom: routing latency increases.** Profile the `appendFileSync`
|
|
200
|
+
call. The canonical inbox is local-filesystem JSONL; on macOS APFS
|
|
201
|
+
/ ext4 / xfs the syscall is sub-millisecond. If unexpectedly slow,
|
|
202
|
+
hoist into a `setImmediate` so the routing branches run first.
|
|
203
|
+
- **Symptom: canonical inbox file grows unboundedly.** Same growth rate
|
|
204
|
+
as the warm-listener queue's rotation cycle — so we already know the
|
|
205
|
+
steady-state. If growth is a problem, add a rotation policy mirroring
|
|
206
|
+
the listener's (compaction at N messages, archive on rotation).
|
|
207
|
+
- **Symptom: HMAC verification fails for canonical entries.** The signing
|
|
208
|
+
key comes from the same HKDF derivation as `writeToInbox` and
|
|
209
|
+
`loadSigningKey` — verified by the round-trip unit test. If a real
|
|
210
|
+
failure shows up, look for an authToken mismatch between processes.
|
|
211
|
+
|
|
212
|
+
## Phase / scope
|
|
213
|
+
|
|
214
|
+
This is the FIRST of five deliverables in topic-8686 (Threadline → Telegram
|
|
215
|
+
Bridge). Subsequent deliverables — dashboard settings, bridge module,
|
|
216
|
+
observability tab, and four-thread backfill — depend on this canonical
|
|
217
|
+
write-path being live. Each will ship as its own PR with its own
|
|
218
|
+
side-effects review.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Side-Effects Review — Threadline Observability Tab
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `threadline-observability-tab`
|
|
4
|
+
**Date:** `2026-05-02`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `self (incident-grounded reasoning)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Fourth of five deliverables in topic-8686. Lights up the dashboard
|
|
11
|
+
"Threadline" tab (added in PR #114) with a real conversation-observability
|
|
12
|
+
view: thread list, color-coded message stream, per-thread metrics,
|
|
13
|
+
filters, and search across all threadline message bodies.
|
|
14
|
+
|
|
15
|
+
Reads three already-existing sources of truth:
|
|
16
|
+
|
|
17
|
+
- `.instar/threadline/inbox.jsonl.active` — every inbound threadline
|
|
18
|
+
message (single source post-PR #113).
|
|
19
|
+
- `.instar/threadline/telegram-bridge-bindings.json` — thread → Telegram
|
|
20
|
+
topic links (single source post-PR #117).
|
|
21
|
+
- `.instar/threadline/thread-resume-map.json` — spawn-session
|
|
22
|
+
bookkeeping (existing).
|
|
23
|
+
|
|
24
|
+
Adds one new source of truth:
|
|
25
|
+
|
|
26
|
+
- `.instar/threadline/outbox.jsonl.active` — every outbound threadline
|
|
27
|
+
message sent via `/threadline/relay-send`. Mirror of the inbox-write
|
|
28
|
+
pattern from PR #113. Gives the conversation view BOTH sides of an
|
|
29
|
+
agent-to-agent thread.
|
|
30
|
+
|
|
31
|
+
Files added:
|
|
32
|
+
|
|
33
|
+
- `src/threadline/ThreadlineObservability.ts` — read-only view layer
|
|
34
|
+
with `listThreads(filters)`, `getThread(threadId)`, `searchMessages(q, limit)`.
|
|
35
|
+
- `tests/unit/ThreadlineObservability.test.ts` — 15 unit cases.
|
|
36
|
+
|
|
37
|
+
Files modified:
|
|
38
|
+
|
|
39
|
+
- `src/threadline/ListenerSessionManager.ts` — adds
|
|
40
|
+
`canonicalOutboxPath` getter and `appendCanonicalOutboxEntry(opts)`
|
|
41
|
+
helper.
|
|
42
|
+
- `src/server/routes.ts`:
|
|
43
|
+
- `RouteContext.threadlineObservability: ThreadlineObservability | null`.
|
|
44
|
+
- Three new endpoints: `GET /threadline/observability/threads`,
|
|
45
|
+
`GET /threadline/observability/threads/:threadId`,
|
|
46
|
+
`GET /threadline/observability/search`.
|
|
47
|
+
- `/threadline/relay-send`: appends a canonical-outbox entry on BOTH
|
|
48
|
+
success paths (local-delivery + relay-delivery) before returning.
|
|
49
|
+
- `src/server/AgentServer.ts` / `src/commands/server.ts` — instantiate
|
|
50
|
+
and pass through `threadlineObservability`.
|
|
51
|
+
- `dashboard/index.html` — replaces the placeholder card on the
|
|
52
|
+
Threadline tab with the conversation view: 280px threads list,
|
|
53
|
+
conversation pane with header metrics + per-message bubbles,
|
|
54
|
+
toolbar with filters + debounced search.
|
|
55
|
+
|
|
56
|
+
## Decision-point inventory
|
|
57
|
+
|
|
58
|
+
- `appendCanonicalOutboxEntry` — **add** — mirror of the inbound
|
|
59
|
+
helper from PR #113. HMAC-signed, JSONL-append, 0o600 perms,
|
|
60
|
+
failure-open.
|
|
61
|
+
- `ThreadlineObservability.listThreads(filters)` — **add** — combines
|
|
62
|
+
inbox + outbox + bindings + thread-resume-map into per-thread
|
|
63
|
+
summaries; sorts most-recent first; supports remoteAgent / since /
|
|
64
|
+
until / hasTopic filters.
|
|
65
|
+
- `ThreadlineObservability.getThread(threadId)` — **add** — returns
|
|
66
|
+
summary + chronological message stream.
|
|
67
|
+
- `ThreadlineObservability.searchMessages(q, limit)` — **add** —
|
|
68
|
+
case-insensitive substring search over inbox+outbox bodies; returns
|
|
69
|
+
hits with snippets bracketed by «...».
|
|
70
|
+
- Three GET endpoints (bearer-auth via global authMiddleware) — **add**.
|
|
71
|
+
- `/threadline/relay-send` outbox writes — **modify** — add one
|
|
72
|
+
helper call on each of two success branches; failure-open.
|
|
73
|
+
- Dashboard JS handlers (`tlObsLoadThreads`, `tlObsLoadThread`,
|
|
74
|
+
`tlObsRunSearch`) — **add**.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 1. Over-block
|
|
79
|
+
|
|
80
|
+
**What legitimate inputs does this change reject that it shouldn't?**
|
|
81
|
+
|
|
82
|
+
The observability layer is read-only and never blocks. The new outbox
|
|
83
|
+
write is failure-open and never throws back to `/threadline/relay-send`
|
|
84
|
+
(the route returns its existing success response either way). No
|
|
85
|
+
over-blocks possible.
|
|
86
|
+
|
|
87
|
+
The endpoints validate query string fields (`hasTopic` only accepts
|
|
88
|
+
`yes` / `no`; everything else is treated as "no filter"). A typo in
|
|
89
|
+
the dashboard's filter UI returns the unfiltered list — which is the
|
|
90
|
+
desirable behavior; the dashboard's controls produce only the valid
|
|
91
|
+
values, and a curl-from-the-CLI user gets an unambiguous result rather
|
|
92
|
+
than a 400.
|
|
93
|
+
|
|
94
|
+
## 2. Under-block
|
|
95
|
+
|
|
96
|
+
**What failure modes does this still miss?**
|
|
97
|
+
|
|
98
|
+
- **No persistence boundary on outbox.** `outbox.jsonl.active` grows
|
|
99
|
+
forever. At the current ~10K msgs/agent envelope this isn't a
|
|
100
|
+
problem, but a future PR should add rotation parallel to the
|
|
101
|
+
warm-listener queue's rotation. Out of scope here.
|
|
102
|
+
- **No streaming SSE for the conversation view.** Threads list and
|
|
103
|
+
conversation are pull-on-activate + manual refresh; new messages
|
|
104
|
+
don't appear without a refresh. Acceptable for v1; a follow-up can
|
|
105
|
+
add the existing `/events` SSE channel for live updates.
|
|
106
|
+
- **No FTS5 index.** `searchMessages` does a full-file scan.
|
|
107
|
+
Sub-100ms at the current envelope; rebuild as FTS5 if it ever
|
|
108
|
+
becomes a complaint. Documented in the class header.
|
|
109
|
+
- **HMAC verification is NOT performed during read.** The
|
|
110
|
+
observability layer reads JSONL lines and parses them as data; it
|
|
111
|
+
doesn't call `verifyEntry` on each row. This is intentional: the
|
|
112
|
+
inbox write uses HMAC for tamper-evidence at write time; reading
|
|
113
|
+
for display doesn't need to re-verify. If an attacker tampers with
|
|
114
|
+
the file at rest, the dashboard would render corrupted bodies, but
|
|
115
|
+
no decision is made on that data — there's no authority surface
|
|
116
|
+
here to subvert.
|
|
117
|
+
|
|
118
|
+
## 3. Level-of-abstraction fit
|
|
119
|
+
|
|
120
|
+
The class is intentionally thin: it composes the existing files into
|
|
121
|
+
view models. Three sources of truth (inbox, outbox, bindings) compose
|
|
122
|
+
into one summary; the `ListenerSessionManager` already owns the writers.
|
|
123
|
+
This matches the pattern set in PR #113 and #117: each class owns a
|
|
124
|
+
single concern, the observability layer is just a join.
|
|
125
|
+
|
|
126
|
+
The dashboard handlers debounce input and bind to existing endpoints
|
|
127
|
+
through the existing `apiFetch` helper. No new client-side state
|
|
128
|
+
machine, no caching beyond what the browser does naturally.
|
|
129
|
+
|
|
130
|
+
## 4. Signal-vs-authority compliance
|
|
131
|
+
|
|
132
|
+
- **Signal:** dashboard query string parameters; text typed into the
|
|
133
|
+
search box.
|
|
134
|
+
- **Authority:** none — this layer makes no decisions, gates nothing,
|
|
135
|
+
blocks nothing. Read-only.
|
|
136
|
+
|
|
137
|
+
The new outbox write follows the same signal-vs-authority shape as
|
|
138
|
+
the inbound write from PR #113: relay-only, failure-open, no decision
|
|
139
|
+
surface. The route's authority (whether to deliver) was already taken
|
|
140
|
+
upstream.
|
|
141
|
+
|
|
142
|
+
## 5. Interactions
|
|
143
|
+
|
|
144
|
+
- **PR #113 (canonical inbox).** Reads the inbox file written by that
|
|
145
|
+
PR. No coupling beyond file format (well-documented JSONL with
|
|
146
|
+
`id, timestamp, from, senderName, trustLevel, threadId, text, hmac`).
|
|
147
|
+
- **PR #114 (settings).** Shares the Threadline dashboard tab — the
|
|
148
|
+
bridge settings card stays at the top, the conversation view sits
|
|
149
|
+
below.
|
|
150
|
+
- **PR #117 (bridge module).** Reads
|
|
151
|
+
`telegram-bridge-bindings.json` to populate the per-thread bridge
|
|
152
|
+
link. The bridge is unaware of the observability layer; the
|
|
153
|
+
observability layer is unaware of the bridge's runtime — they
|
|
154
|
+
communicate exclusively through the on-disk file.
|
|
155
|
+
- **`thread-resume-map.json`.** The class accepts both the legacy
|
|
156
|
+
flat shape (`{threadId: ...}`) and the newer `{threads: {...}}`
|
|
157
|
+
shape, so it works against either.
|
|
158
|
+
- **`/threadline/relay-send`.** Two new helper calls on the success
|
|
159
|
+
paths. Same failure-open pattern as PR #113's inbox hoist.
|
|
160
|
+
|
|
161
|
+
## 6. Rollback cost
|
|
162
|
+
|
|
163
|
+
- Drop the three observability endpoints + the dashboard handlers →
|
|
164
|
+
the Threadline tab loses the conversation view but the bridge
|
|
165
|
+
settings card from PR #114 keeps working.
|
|
166
|
+
- Drop the outbox helper + the two route hooks → outbound messages
|
|
167
|
+
no longer accrue in `outbox.jsonl.active`, but the relay-send
|
|
168
|
+
route still functions. The conversation view degrades to inbound-only.
|
|
169
|
+
- The on-disk `outbox.jsonl.active` file is JSONL-append-only with no
|
|
170
|
+
cross-references; it can be `rm`'d safely if rolled back.
|
|
171
|
+
|
|
172
|
+
No schema migrations, no shared-state changes, no new processes.
|
|
173
|
+
|
|
174
|
+
## Plan if a regression appears
|
|
175
|
+
|
|
176
|
+
- **Symptom: dashboard tab errors loading threads.** Check
|
|
177
|
+
`apiFetch('/threadline/observability/threads')` — 503 means
|
|
178
|
+
`threadlineObservability` is null in the route context (server-side
|
|
179
|
+
bootstrap regression). 200 with empty threads is the correct
|
|
180
|
+
response for a fresh agent.
|
|
181
|
+
- **Symptom: search slow.** The full-file scan is bounded by
|
|
182
|
+
`inbox.jsonl.active` + `outbox.jsonl.active` line counts. Profile;
|
|
183
|
+
if pathological, add an FTS5 index keyed on `(threadId, timestamp)`.
|
|
184
|
+
- **Symptom: outbound messages missing from conversation view.**
|
|
185
|
+
Either (a) the relay-send route's outbox-append helper threw and
|
|
186
|
+
was caught, or (b) the threadline message went out via a different
|
|
187
|
+
path (e.g. legacy direct relay client). Check the warn lines in
|
|
188
|
+
the agent log. Worst case: roll back the outbox helper additions
|
|
189
|
+
and rely on the bridge bindings file alone (which still gives
|
|
190
|
+
thread-level visibility).
|
|
191
|
+
|
|
192
|
+
## Phase / scope
|
|
193
|
+
|
|
194
|
+
Fourth of five deliverables in topic-8686:
|
|
195
|
+
|
|
196
|
+
1. (a) Canonical inbox write-path — **MERGED** (#113).
|
|
197
|
+
2. (2) Settings surface — **MERGED** (#114).
|
|
198
|
+
3. (b) Bridge module — **MERGED** (#117).
|
|
199
|
+
4. **(4) Observability tab — THIS PR.**
|
|
200
|
+
5. (c) Backfill four open threads — final, one-shot script.
|
|
201
|
+
|
|
202
|
+
After (4) merges, the Threadline tab is the user's single pane of
|
|
203
|
+
glass for agent-to-agent traffic: every thread, every message,
|
|
204
|
+
filters by remote agent / date / has-topic, search, and a clear
|
|
205
|
+
visual signal of which threads have a Telegram topic and which have
|
|
206
|
+
been spawned into a Claude Code session.
|