instar 0.28.75 → 0.28.77
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 +306 -0
- package/dist/cli.js +5 -4
- package/dist/cli.js.map +1 -1
- package/dist/commands/discovery.d.ts.map +1 -1
- package/dist/commands/discovery.js +2 -1
- package/dist/commands/discovery.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +22 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/job.d.ts.map +1 -1
- package/dist/commands/job.js +2 -1
- package/dist/commands/job.js.map +1 -1
- package/dist/commands/ledgerCleanup.d.ts.map +1 -1
- package/dist/commands/ledgerCleanup.js +2 -1
- package/dist/commands/ledgerCleanup.js.map +1 -1
- package/dist/commands/listener.d.ts.map +1 -1
- package/dist/commands/listener.js +7 -6
- package/dist/commands/listener.js.map +1 -1
- package/dist/commands/nuke.d.ts.map +1 -1
- package/dist/commands/nuke.js +11 -15
- package/dist/commands/nuke.js.map +1 -1
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +35 -3
- package/dist/commands/server.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +11 -9
- 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 -4
- package/dist/commands/slack-cli.js.map +1 -1
- package/dist/commands/whatsapp.d.ts.map +1 -1
- package/dist/commands/whatsapp.js +2 -1
- package/dist/commands/whatsapp.js.map +1 -1
- package/dist/commands/worktree.d.ts.map +1 -1
- package/dist/commands/worktree.js +2 -1
- package/dist/commands/worktree.js.map +1 -1
- package/dist/core/AgentConnector.d.ts.map +1 -1
- package/dist/core/AgentConnector.js +9 -7
- package/dist/core/AgentConnector.js.map +1 -1
- package/dist/core/AgentRegistry.d.ts.map +1 -1
- package/dist/core/AgentRegistry.js +3 -2
- package/dist/core/AgentRegistry.js.map +1 -1
- package/dist/core/AutoDispatcher.d.ts.map +1 -1
- package/dist/core/AutoDispatcher.js +2 -1
- package/dist/core/AutoDispatcher.js.map +1 -1
- package/dist/core/AutoUpdater.d.ts.map +1 -1
- package/dist/core/AutoUpdater.js +2 -1
- package/dist/core/AutoUpdater.js.map +1 -1
- package/dist/core/AutonomousEvolution.d.ts.map +1 -1
- package/dist/core/AutonomousEvolution.js +2 -1
- package/dist/core/AutonomousEvolution.js.map +1 -1
- package/dist/core/BackupManager.d.ts.map +1 -1
- package/dist/core/BackupManager.js +2 -1
- package/dist/core/BackupManager.js.map +1 -1
- package/dist/core/BranchManager.d.ts.map +1 -1
- package/dist/core/BranchManager.js +3 -2
- package/dist/core/BranchManager.js.map +1 -1
- package/dist/core/CaffeinateManager.d.ts.map +1 -1
- package/dist/core/CaffeinateManager.js +2 -1
- package/dist/core/CaffeinateManager.js.map +1 -1
- package/dist/core/DeferredDispatchTracker.d.ts.map +1 -1
- package/dist/core/DeferredDispatchTracker.js +2 -1
- package/dist/core/DeferredDispatchTracker.js.map +1 -1
- package/dist/core/DispatchManager.d.ts.map +1 -1
- package/dist/core/DispatchManager.js +3 -2
- package/dist/core/DispatchManager.js.map +1 -1
- package/dist/core/EvolutionManager.d.ts.map +1 -1
- package/dist/core/EvolutionManager.js +2 -1
- package/dist/core/EvolutionManager.js.map +1 -1
- package/dist/core/ExecutionJournal.d.ts.map +1 -1
- package/dist/core/ExecutionJournal.js +2 -1
- package/dist/core/ExecutionJournal.js.map +1 -1
- package/dist/core/FeedbackManager.d.ts.map +1 -1
- package/dist/core/FeedbackManager.js +2 -1
- package/dist/core/FeedbackManager.js.map +1 -1
- package/dist/core/FileClassifier.d.ts.map +1 -1
- package/dist/core/FileClassifier.js +8 -13
- package/dist/core/FileClassifier.js.map +1 -1
- package/dist/core/ForegroundRestartWatcher.d.ts.map +1 -1
- package/dist/core/ForegroundRestartWatcher.js +3 -2
- package/dist/core/ForegroundRestartWatcher.js.map +1 -1
- package/dist/core/GitStateManager.d.ts.map +1 -1
- package/dist/core/GitStateManager.js +3 -11
- package/dist/core/GitStateManager.js.map +1 -1
- package/dist/core/GitSync.d.ts.map +1 -1
- package/dist/core/GitSync.js +6 -3
- package/dist/core/GitSync.js.map +1 -1
- package/dist/core/GlobalInstallCleanup.d.ts.map +1 -1
- package/dist/core/GlobalInstallCleanup.js +3 -2
- package/dist/core/GlobalInstallCleanup.js.map +1 -1
- package/dist/core/GlobalSecretStore.d.ts.map +1 -1
- package/dist/core/GlobalSecretStore.js +3 -2
- package/dist/core/GlobalSecretStore.js.map +1 -1
- package/dist/core/HandoffManager.d.ts.map +1 -1
- package/dist/core/HandoffManager.js +5 -3
- 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 -1
- package/dist/core/LedgerSessionRegistry.js.map +1 -1
- package/dist/core/MachineIdentity.d.ts.map +1 -1
- package/dist/core/MachineIdentity.js +2 -1
- 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 -5
- 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 -44
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/ProjectMapper.d.ts.map +1 -1
- package/dist/core/ProjectMapper.js +5 -9
- package/dist/core/ProjectMapper.js.map +1 -1
- package/dist/core/RelationshipManager.d.ts.map +1 -1
- package/dist/core/RelationshipManager.js +4 -3
- package/dist/core/RelationshipManager.js.map +1 -1
- package/dist/core/SafeFsExecutor.d.ts +41 -0
- package/dist/core/SafeFsExecutor.d.ts.map +1 -0
- package/dist/core/SafeFsExecutor.js +146 -0
- package/dist/core/SafeFsExecutor.js.map +1 -0
- package/dist/core/SafeGitExecutor.d.ts +145 -0
- package/dist/core/SafeGitExecutor.d.ts.map +1 -0
- package/dist/core/SafeGitExecutor.js +717 -0
- package/dist/core/SafeGitExecutor.js.map +1 -0
- package/dist/core/ScopeVerifier.d.ts.map +1 -1
- package/dist/core/ScopeVerifier.js +3 -5
- package/dist/core/ScopeVerifier.js.map +1 -1
- package/dist/core/SecretStore.d.ts.map +1 -1
- package/dist/core/SecretStore.js +2 -1
- package/dist/core/SecretStore.js.map +1 -1
- package/dist/core/SharedStateLedger.d.ts.map +1 -1
- package/dist/core/SharedStateLedger.js +2 -1
- package/dist/core/SharedStateLedger.js.map +1 -1
- package/dist/core/SoulManager.d.ts.map +1 -1
- package/dist/core/SoulManager.js +3 -2
- package/dist/core/SoulManager.js.map +1 -1
- package/dist/core/StateManager.d.ts.map +1 -1
- package/dist/core/StateManager.js +4 -3
- package/dist/core/StateManager.js.map +1 -1
- package/dist/core/SyncOrchestrator.d.ts.map +1 -1
- package/dist/core/SyncOrchestrator.js +6 -4
- package/dist/core/SyncOrchestrator.js.map +1 -1
- package/dist/core/UpdateChecker.d.ts.map +1 -1
- package/dist/core/UpdateChecker.js +3 -2
- package/dist/core/UpdateChecker.js.map +1 -1
- package/dist/core/UpgradeGuideProcessor.d.ts.map +1 -1
- package/dist/core/UpgradeGuideProcessor.js +3 -2
- package/dist/core/UpgradeGuideProcessor.js.map +1 -1
- package/dist/core/WorktreeManager.d.ts.map +1 -1
- package/dist/core/WorktreeManager.js +9 -7
- package/dist/core/WorktreeManager.js.map +1 -1
- package/dist/knowledge/KnowledgeManager.d.ts.map +1 -1
- package/dist/knowledge/KnowledgeManager.js +2 -1
- 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 -59
- package/dist/lifeline/ServerSupervisor.js.map +1 -1
- package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
- package/dist/lifeline/TelegramLifeline.js +10 -3
- 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 -1
- package/dist/lifeline/droppedMessages.js.map +1 -1
- package/dist/memory/EpisodicMemory.d.ts.map +1 -1
- package/dist/memory/EpisodicMemory.js +2 -1
- package/dist/memory/EpisodicMemory.js.map +1 -1
- package/dist/memory/TopicMemory.d.ts.map +1 -1
- package/dist/memory/TopicMemory.js +5 -4
- package/dist/memory/TopicMemory.js.map +1 -1
- package/dist/messaging/AgentTokenManager.d.ts.map +1 -1
- package/dist/messaging/AgentTokenManager.js +2 -1
- package/dist/messaging/AgentTokenManager.js.map +1 -1
- package/dist/messaging/DropPickup.d.ts.map +1 -1
- package/dist/messaging/DropPickup.js +2 -1
- package/dist/messaging/DropPickup.js.map +1 -1
- package/dist/messaging/GitSyncTransport.d.ts.map +1 -1
- package/dist/messaging/GitSyncTransport.js +4 -3
- package/dist/messaging/GitSyncTransport.js.map +1 -1
- package/dist/messaging/MessageStore.d.ts.map +1 -1
- package/dist/messaging/MessageStore.js +3 -2
- package/dist/messaging/MessageStore.js.map +1 -1
- package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
- package/dist/messaging/TelegramAdapter.js +5 -4
- 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 -2
- 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 -2
- 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 -1
- 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 -1
- 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 -1
- 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 -4
- package/dist/moltbridge/ProfileCompiler.js.map +1 -1
- package/dist/monitoring/CommitmentTracker.d.ts.map +1 -1
- package/dist/monitoring/CommitmentTracker.js +2 -1
- package/dist/monitoring/CommitmentTracker.js.map +1 -1
- package/dist/monitoring/CredentialProvider.d.ts.map +1 -1
- package/dist/monitoring/CredentialProvider.js +2 -1
- 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 -1
- package/dist/monitoring/HealthChecker.js.map +1 -1
- package/dist/monitoring/HookEventReceiver.d.ts.map +1 -1
- package/dist/monitoring/HookEventReceiver.js +2 -1
- package/dist/monitoring/HookEventReceiver.js.map +1 -1
- package/dist/monitoring/InstructionsVerifier.d.ts.map +1 -1
- package/dist/monitoring/InstructionsVerifier.js +2 -1
- package/dist/monitoring/InstructionsVerifier.js.map +1 -1
- package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
- package/dist/monitoring/PresenceProxy.js +5 -4
- package/dist/monitoring/PresenceProxy.js.map +1 -1
- package/dist/monitoring/QuotaTracker.d.ts.map +1 -1
- package/dist/monitoring/QuotaTracker.js +2 -1
- package/dist/monitoring/QuotaTracker.js.map +1 -1
- package/dist/monitoring/SessionMigrator.d.ts.map +1 -1
- package/dist/monitoring/SessionMigrator.js +2 -1
- package/dist/monitoring/SessionMigrator.js.map +1 -1
- package/dist/monitoring/SessionRecovery.d.ts.map +1 -1
- package/dist/monitoring/SessionRecovery.js +2 -1
- package/dist/monitoring/SessionRecovery.js.map +1 -1
- package/dist/monitoring/TelemetryAuth.d.ts.map +1 -1
- package/dist/monitoring/TelemetryAuth.js +3 -2
- package/dist/monitoring/TelemetryAuth.js.map +1 -1
- package/dist/monitoring/TokenLedger.d.ts +91 -0
- package/dist/monitoring/TokenLedger.d.ts.map +1 -0
- package/dist/monitoring/TokenLedger.js +426 -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 -2
- package/dist/monitoring/TriageOrchestrator.js.map +1 -1
- package/dist/monitoring/WorktreeReaper.d.ts.map +1 -1
- package/dist/monitoring/WorktreeReaper.js +5 -4
- 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 -2
- 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 -4
- package/dist/paste/PasteManager.js.map +1 -1
- package/dist/publishing/PrivateViewer.d.ts.map +1 -1
- package/dist/publishing/PrivateViewer.js +2 -1
- package/dist/publishing/PrivateViewer.js.map +1 -1
- package/dist/scheduler/JobScheduler.d.ts.map +1 -1
- package/dist/scheduler/JobScheduler.js +2 -1
- package/dist/scheduler/JobScheduler.js.map +1 -1
- package/dist/server/AgentServer.d.ts +18 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +186 -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 +69 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +545 -16
- package/dist/server/routes.js.map +1 -1
- package/dist/threadline/AgentDiscovery.d.ts.map +1 -1
- package/dist/threadline/AgentDiscovery.js +2 -1
- package/dist/threadline/AgentDiscovery.js.map +1 -1
- package/dist/threadline/AgentTrustManager.d.ts.map +1 -1
- package/dist/threadline/AgentTrustManager.js +2 -1
- package/dist/threadline/AgentTrustManager.js.map +1 -1
- package/dist/threadline/CircuitBreaker.d.ts.map +1 -1
- package/dist/threadline/CircuitBreaker.js +2 -1
- package/dist/threadline/CircuitBreaker.js.map +1 -1
- package/dist/threadline/ComputeMeter.d.ts.map +1 -1
- package/dist/threadline/ComputeMeter.js +2 -1
- package/dist/threadline/ComputeMeter.js.map +1 -1
- package/dist/threadline/ContextThreadMap.d.ts.map +1 -1
- package/dist/threadline/ContextThreadMap.js +2 -1
- 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 -1
- package/dist/threadline/InvitationManager.js.map +1 -1
- package/dist/threadline/ListenerSessionManager.d.ts +24 -0
- package/dist/threadline/ListenerSessionManager.d.ts.map +1 -1
- package/dist/threadline/ListenerSessionManager.js +38 -0
- package/dist/threadline/ListenerSessionManager.js.map +1 -1
- package/dist/threadline/MCPAuth.d.ts.map +1 -1
- package/dist/threadline/MCPAuth.js +2 -1
- package/dist/threadline/MCPAuth.js.map +1 -1
- package/dist/threadline/PipeSessionSpawner.d.ts.map +1 -1
- package/dist/threadline/PipeSessionSpawner.js +3 -2
- package/dist/threadline/PipeSessionSpawner.js.map +1 -1
- package/dist/threadline/RateLimiter.d.ts.map +1 -1
- package/dist/threadline/RateLimiter.js +2 -1
- 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 -1
- 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/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 -1
- package/dist/threadline/ThreadlineBootstrap.js.map +1 -1
- package/dist/threadline/WakeSocketServer.d.ts.map +1 -1
- package/dist/threadline/WakeSocketServer.js +3 -2
- 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 -2
- package/dist/threadline/listener-daemon.js.map +1 -1
- package/dist/users/UserManager.d.ts.map +1 -1
- package/dist/users/UserManager.js +2 -1
- package/dist/users/UserManager.js.map +1 -1
- package/dist/users/UserOnboarding.d.ts.map +1 -1
- package/dist/users/UserOnboarding.js +2 -1
- 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 -1
- package/dist/utils/jsonl-rotation.js.map +1 -1
- package/package.json +4 -2
- package/scripts/add-migration-marker.js +121 -0
- package/scripts/analyze-release.js +7 -6
- package/scripts/check-contract-evidence.js +27 -8
- package/scripts/destructive-command-shim.js +1 -0
- package/scripts/generate-builtin-manifest.cjs +1 -0
- package/scripts/lint-no-direct-destructive.js +617 -0
- package/scripts/lint-template-sha-history.ts +183 -0
- package/scripts/migrate-incident-2026-04-17.mjs +2 -1
- package/scripts/pre-push-gate.js +24 -0
- package/scripts/run-migration.js +500 -0
- package/scripts/test-bootstrap-relay.mjs +2 -1
- package/scripts/verify-deployed-templates.ts +87 -0
- package/scripts/worktree-commit-msg-hook.js +4 -0
- package/scripts/worktree-precommit-gate.js +1 -0
- package/src/data/builtin-manifest.json +139 -131
- package/src/templates/scripts/telegram-reply.sh +318 -13
- package/upgrades/0.28.76.md +67 -0
- package/upgrades/0.28.77.md +133 -0
- package/upgrades/side-effects/0.28.76.md +76 -0
- package/upgrades/side-effects/agent-health-alert-authority-routing.md +121 -0
- package/upgrades/side-effects/comprehensive-destructive-tool-containment-foundation.md +74 -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-canonical-inbox-write.md +218 -0
- package/upgrades/side-effects/threadline-tg-bridge-settings-surface.md +208 -0
- package/upgrades/side-effects/token-ledger-phase1.md +123 -0
- package/upgrades/NEXT.md +0 -53
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Side-Effects Review — telegram-delivery-robustness Layer 3 (DeliveryFailureSentinel)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `telegram-delivery-robustness-layer-3`
|
|
4
|
+
**Date:** `2026-04-27`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `subagent (Claude, fresh context)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Ships Layer 3 of the `telegram-delivery-robustness` spec on top of the
|
|
11
|
+
already-merged Layer 1 (port-from-config + agent-id binding, PR #100,
|
|
12
|
+
commit `f9b5e3bb`) and Layer 2 (durable SQLite queue + `delivery_failed`
|
|
13
|
+
event endpoint, PR #101, commit `5b953c17`). Layer 3 introduces an
|
|
14
|
+
in-process `DeliveryFailureSentinel` that reads the per-agent SQLite
|
|
15
|
+
queue, runs the recovery state machine (detect → claim → re-resolve
|
|
16
|
+
config → `/whoami` → re-tone-gate → `POST /telegram/reply` with
|
|
17
|
+
`X-Instar-DeliveryId` header → finalize OR escalate), and is feature-
|
|
18
|
+
flag-gated default-OFF via `monitoring.deliveryFailureSentinel.enabled`.
|
|
19
|
+
|
|
20
|
+
Files added:
|
|
21
|
+
|
|
22
|
+
- `src/monitoring/delivery-failure-sentinel.ts` — sentinel class (≈530 LoC).
|
|
23
|
+
- `src/monitoring/delivery-failure-sentinel/recovery-policy.ts` — pure deterministic policy evaluator.
|
|
24
|
+
- `src/messaging/system-templates.ts` — fixed-template constants + boot-time SHA verification + system-template allow-list.
|
|
25
|
+
- `src/messaging/whoami-cache.ts` — 60s in-process cache keyed on `(port, sha256(token), agentId, config-mtime)`.
|
|
26
|
+
- `src/messaging/secret-patterns.ts` — compiled-in redaction patterns.
|
|
27
|
+
- `src/messaging/local-tone-check.ts` — in-process wrapper around `MessagingToneGate`.
|
|
28
|
+
- `src/server/boot-id.ts` — synchronous-before-listener boot id (16 bytes, mode 0600).
|
|
29
|
+
|
|
30
|
+
Files modified:
|
|
31
|
+
|
|
32
|
+
- `src/server/routes.ts` — `X-Instar-DeliveryId` 24h LRU dedup, `X-Instar-System` template-bypass on `/telegram/reply`, new `GET /delivery-queue` route.
|
|
33
|
+
- `src/server/AgentServer.ts` — wires `getOrCreateBootId` before listener bind; spins up `DeliveryFailureSentinel` after listener bind, gated on the feature flag.
|
|
34
|
+
- `src/server/WebSocketManager.ts` — adds `subscribeEvents()` for in-process listeners (no schema change for dashboard clients).
|
|
35
|
+
- `src/messaging/pending-relay-store.ts` — adds `selectClaimable(nowIso, limit)` and `purgeStaleClaimable(cutoffIso)` (no schema change; idempotent over the same DB created by Layer 2).
|
|
36
|
+
|
|
37
|
+
Tests added: 5 unit (`recovery-policy`, `system-templates`, `whoami-cache`, `boot-id`, `delivery-queue-route`) + 4 integration (`sentinel-recovery`, `sentinel-circuit-breaker`, `sentinel-tone-gate-recovery`, `sentinel-stampede-digest`).
|
|
38
|
+
|
|
39
|
+
## Decision-point inventory
|
|
40
|
+
|
|
41
|
+
- `DeliveryFailureSentinel.processRow` — **add** — runs the recovery state machine on a single queue row.
|
|
42
|
+
- `evaluatePolicy` (recovery-policy) — **add** — pure deterministic mapping of `(http_code, attempts, time_since_first)` to `{retry|escalate|finalize-*}`.
|
|
43
|
+
- `/telegram/reply` `X-Instar-DeliveryId` LRU dedup — **add** — server-side 24h LRU returns 200-idempotent on duplicate delivery_id.
|
|
44
|
+
- `/telegram/reply` `X-Instar-System` bypass — **add** — bypasses tone gate iff body matches a known compiled-in template.
|
|
45
|
+
- `/delivery-queue` route — **add** — read-only depth/oldest-age/by-state introspection.
|
|
46
|
+
- Tone gate authority (`MessagingToneGate.review`) — **pass-through** — sentinel calls `review()` directly via `local-tone-check`, never overrides its decision.
|
|
47
|
+
- WebSocketManager `broadcastEvent` — **modify** — also notifies in-process subscribers; existing dashboard clients see no change.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 1. Over-block
|
|
52
|
+
|
|
53
|
+
**What legitimate inputs does this change reject that it shouldn't?**
|
|
54
|
+
|
|
55
|
+
- The new `X-Instar-System` bypass is **deny-by-default** — only bodies that match a compiled-in template (regex- or SHA-bound) bypass the tone gate. Arbitrary system-flagged text falls through to the normal gate. There is no over-block here; the bypass narrows authority, it doesn't widen it.
|
|
56
|
+
- The `X-Instar-DeliveryId` LRU returns 200-idempotent on duplicate header values. A legitimate sender that intentionally retries a `delivery_id` (operator manually replays a row) will see the second send swallowed. Mitigation: the LRU is bounded at 10K entries with 24h TTL, so a deliberate delay > 24h triggers a fresh send.
|
|
57
|
+
- The recovery-policy escalates on `403/unstructured`. A server returning a non-JSON 403 body (rare, but possible from intermediate proxies) will skip retry. Acceptable: spec § 3d step 5 is explicit about default-deny on this code path.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 2. Under-block
|
|
62
|
+
|
|
63
|
+
**What failure modes does this still miss?**
|
|
64
|
+
|
|
65
|
+
- **WebSocket-disconnected dashboard.** `broadcastEvent` notifies in-process subscribers BEFORE the WebSocket fan-out, so the sentinel reacts even with no clients. But if a server crashes between the script-side enqueue and the SSE event, the SSE primary path is lost and recovery falls to the 5-minute watchdog tick. This is the spec-acknowledged backstop, not a new gap.
|
|
66
|
+
- **Stampede summarization across ticks.** The `stampedeThreshold` check runs per-tick. A topic that accrues 4 entries per tick over 3 ticks (12 total) does not trigger the digest — each tick only sees 4. This is intentional: the digest's purpose is "compress a single outage's burst into one user-visible event", not "police a slow-burn."
|
|
67
|
+
- **Tone-gate failure-open.** When the tone gate provider is unavailable, `local-tone-check` returns `passed: true, failedOpen: true`. A queued message with technical leakage would be re-sent. Mitigation: the original send went through the same gate (which presumably passed); if the gate is now down, we don't have authority to override its prior pass. Documented in `local-tone-check.ts`.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 3. Level-of-abstraction fit
|
|
72
|
+
|
|
73
|
+
**Is this at the right layer?**
|
|
74
|
+
|
|
75
|
+
The split between `recovery-policy.ts` (pure, deterministic) and
|
|
76
|
+
`delivery-failure-sentinel.ts` (lifecycle, I/O) matches the spec's
|
|
77
|
+
signal-vs-authority framing exactly:
|
|
78
|
+
|
|
79
|
+
- The sentinel does **not** reason about content. It runs a state machine
|
|
80
|
+
whose transitions are entirely determined by HTTP codes and counts.
|
|
81
|
+
- All user-visible content is fixed-template, with template integrity
|
|
82
|
+
verified at boot.
|
|
83
|
+
- All tone judgment is delegated to `MessagingToneGate.review` via
|
|
84
|
+
`local-tone-check`.
|
|
85
|
+
|
|
86
|
+
This is the right shape. The alternative — embedding policy decisions in
|
|
87
|
+
`AgentServer` or `routes.ts` — would couple recovery to HTTP handlers
|
|
88
|
+
and make the policy untestable in isolation. The current split keeps
|
|
89
|
+
the policy in 250 LoC of pure code with exhaustive unit coverage.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 4. Signal vs authority compliance
|
|
94
|
+
|
|
95
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
96
|
+
|
|
97
|
+
**Does this change hold blocking authority with brittle logic?**
|
|
98
|
+
|
|
99
|
+
- [x] **No** — this change produces a signal consumed by an existing smart gate (the `MessagingToneGate`). The sentinel runs a deterministic policy on enumerable HTTP codes, never on free-form content. User-visible text emitted by the sentinel is fixed-template only, and the templates were tone-gate-reviewed at code-review time. Per spec § 5 the sentinel is "a deterministic policy engine for retry mechanics + a fixed-template message emitter routed through the same single tone-gate authority."
|
|
100
|
+
|
|
101
|
+
The `X-Instar-System` server-side bypass deserves a closer look:
|
|
102
|
+
|
|
103
|
+
- The bypass is restricted to a **compiled-in allow-list** verified by SHA-256 (static templates) and bounded regex (parameterized templates with enumerated `{category}`).
|
|
104
|
+
- The allow-list cannot be modified at runtime — it ships in `dist/messaging/system-templates.js`.
|
|
105
|
+
- The sentinel sets `X-Instar-System: true` on its template sends; non-template bodies fail through to the normal gate.
|
|
106
|
+
- This is the bypass shape the spec calls for in § 3f. It does not introduce a new content authority.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 5. Interactions
|
|
111
|
+
|
|
112
|
+
**Does this interact with existing checks, recovery paths, or infrastructure?**
|
|
113
|
+
|
|
114
|
+
- **Shadowing:** `X-Instar-DeliveryId` LRU runs BEFORE the tone gate. A duplicate replay returns 200-idempotent without the gate ever running. This is intentional — a duplicate header proves a prior send already went through the gate. No tone-gate event is emitted for the dedup return; the original send's gate event remains the only record.
|
|
115
|
+
- **Double-fire:** the sentinel and the script-side detector (Layer 2b) cannot fire on the same row. The script INSERTs with `state='queued'`; the sentinel transitions to `'claimed'` before any send. INSERT OR IGNORE on the same `delivery_id` is a no-op (Layer 2a property), so a tight-loop sender cannot enqueue the same row twice.
|
|
116
|
+
- **Races:** lease ownership uses `<bootId>:<pid>:<leaseUntil>`. PID reuse across reboots is handled by bootId mismatch (always reclaimable). Two sentinels on the same DB (shared worktree case) race on the `transition('claimed')` UPDATE; the loser sees `changes=0` and skips the row this tick.
|
|
117
|
+
- **Feedback loops:** the sentinel's recovered-marker send is fire-and-forget. A failed marker is logged and dropped — never queued. This prevents the "sentinel queues its own retry on its own follow-up" cascade.
|
|
118
|
+
- **WSManager subscribers:** new `subscribeEvents` API. Existing `broadcastEvent` callers see no behavioral change; in-process subscribers run on the same code path before the WebSocket fan-out. A subscriber that throws is logged but does not block the broadcast.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 6. External surfaces
|
|
123
|
+
|
|
124
|
+
**Does this change anything visible outside the immediate code path?**
|
|
125
|
+
|
|
126
|
+
- **Wire format:** `/telegram/reply` accepts two new optional headers (`X-Instar-DeliveryId`, `X-Instar-System`). Existing callers that don't send them see no behavioral change.
|
|
127
|
+
- **New endpoint:** `GET /delivery-queue` (authed). Read-only; safe for dashboard polling.
|
|
128
|
+
- **Persistent state:** the sentinel reads the SQLite queue created by Layer 2 (`pending-relay.<agentId>.sqlite`). It writes lease metadata (`claimed_by`, `next_attempt_at`, `state` transitions) but does not change the schema. Layer 2's idempotent ALTER pattern remains compatible.
|
|
129
|
+
- **boot.id file:** new file at `<stateDir>/state/boot.id` (16 bytes, mode 0600). Persists across restarts within the same instar minor version. Operators upgrading multiple minor versions in quick succession will see one rotation per minor bump — this is intentional (queue semantics may change across minor versions, so prior-version leases must not survive).
|
|
130
|
+
- **Telegram users:** when the feature flag is OFF (default), users see no change. When ON and recovery succeeds, users see (a) the original message delivered up to 24h after the original outage, (b) a `_(recovered)_` follow-up marker ~2s later. When recovery fails, users see one fixed-template escalation message per topic; a circuit breaker prevents flooding.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 7. Rollback cost
|
|
135
|
+
|
|
136
|
+
**If this turns out wrong in production, what's the back-out?**
|
|
137
|
+
|
|
138
|
+
- **Hot-fix release:** revert the source. Existing queue rows become inert (no sentinel reads them). Layer 1 and Layer 2 keep working — the originating incident is still fixed by Layer 1 alone.
|
|
139
|
+
- **Feature flag toggle:** the cleanest rollback is `monitoring.deliveryFailureSentinel.enabled = false`. Default is already OFF; only opt-in agents need to flip the flag back. No data migration, no user-visible regression.
|
|
140
|
+
- **Persistent state:** `boot.id` and the SQLite queue both live under `.instar/state/` and are gitignored (Layer 2 added the patterns). No backup capture, no cross-machine replay. A rollback that wipes both files leaves the agent in a clean state.
|
|
141
|
+
- **User visibility during rollback:** an agent mid-recovery when the flag flips OFF will leave a row in `state='claimed'` with a stale lease. Next sentinel run (after re-enabling) reclaims it via bootId/lease-stale checks. No user-visible regression.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Conclusion
|
|
146
|
+
|
|
147
|
+
The Layer 3 implementation matches the spec exactly. The split into a
|
|
148
|
+
pure policy module + a stateful sentinel made the policy exhaustively
|
|
149
|
+
testable (32 unit tests covering the entire decision table). The
|
|
150
|
+
`X-Instar-System` bypass is the most security-sensitive new surface,
|
|
151
|
+
and it's structurally constrained — compiled-in allow-list + bounded
|
|
152
|
+
regex on parameterized templates + SHA-256 on static templates. The
|
|
153
|
+
default-OFF feature flag means no current agent is affected by this
|
|
154
|
+
PR's runtime behavior unless they explicitly opt in.
|
|
155
|
+
|
|
156
|
+
Two design decisions made during the review:
|
|
157
|
+
|
|
158
|
+
1. The `WhoamiCache` originally keyed only on `(port, tokenHash)`. After
|
|
159
|
+
re-reading § 1c, I added `agentId` to the key so a multi-agent host
|
|
160
|
+
running multiple servers on different ports cannot poison each other's
|
|
161
|
+
caches. (This was already implicit in the spec via the `X-Instar-AgentId`
|
|
162
|
+
header on `/whoami`, but explicit keying makes the invariant local.)
|
|
163
|
+
2. The recovery-policy originally retried on attempt = MAX_ATTEMPTS. After
|
|
164
|
+
re-reading § 3c ("9 steps... attempts exhausted"), I changed the
|
|
165
|
+
threshold to `attempts >= MAX_ATTEMPTS` so the 9th attempt's failure
|
|
166
|
+
escalates rather than scheduling a 10th. The unit test was updated
|
|
167
|
+
accordingly.
|
|
168
|
+
|
|
169
|
+
Ship.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Second-pass review (if required)
|
|
174
|
+
|
|
175
|
+
**Reviewer:** subagent (Claude, fresh context)
|
|
176
|
+
**Independent read of the artifact: concur**
|
|
177
|
+
|
|
178
|
+
The Layer 3 implementation correctly factors the deterministic policy
|
|
179
|
+
into a pure module, isolates user-visible content into compiled-in
|
|
180
|
+
templates with boot-time SHA verification, and gates everything behind
|
|
181
|
+
a default-OFF feature flag. The `X-Instar-DeliveryId` LRU-before-gate
|
|
182
|
+
ordering is the correct precedence: a duplicate `delivery_id` proves a
|
|
183
|
+
prior gate pass, so re-running the gate on the same body would be wasted
|
|
184
|
+
work and could spuriously block on a tone-gate provider transient.
|
|
185
|
+
|
|
186
|
+
One concern raised, addressed in this PR before commit:
|
|
187
|
+
|
|
188
|
+
- The `WhoamiCache` cache key initially omitted `agentId`. On a host
|
|
189
|
+
with multiple servers sharing a token (uncommon but possible during
|
|
190
|
+
config rotation drills), this would have produced cross-agent
|
|
191
|
+
whoami leakage. Fix: include `agentId` in the cache key.
|
|
192
|
+
|
|
193
|
+
No other concerns at the medium-or-higher threshold.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Evidence pointers
|
|
198
|
+
|
|
199
|
+
- Unit tests: `tests/unit/recovery-policy.test.ts` (32 cases), `tests/unit/system-templates.test.ts` (15 cases), `tests/unit/whoami-cache.test.ts` (6 cases), `tests/unit/boot-id.test.ts` (8 cases), `tests/unit/delivery-queue-route.test.ts` (2 cases).
|
|
200
|
+
- Integration tests: `tests/integration/sentinel-recovery.test.ts` (2 cases — happy path + agent-id mismatch retry), `tests/integration/sentinel-circuit-breaker.test.ts` (1 case — 5 failures → suspend → resume on auth-hash change), `tests/integration/sentinel-tone-gate-recovery.test.ts` (1 case — re-gate rejection finalizes as `delivered-tone-gated` with meta-notice), `tests/integration/sentinel-stampede-digest.test.ts` (1 case — 6 entries → digest + 5 dropped).
|
|
201
|
+
- Spec: `docs/specs/telegram-delivery-robustness.md` § 4 Layer 3.
|
|
202
|
+
- Predecessor PRs: #100 (Layer 1, `f9b5e3bb`), #101 (Layer 2, `5b953c17`).
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
# Side-Effects Review — telegram-delivery-robustness Layer 7 (Templates Drift Verifier)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `telegram-delivery-robustness-layer-7`
|
|
4
|
+
**Date:** `2026-04-27`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required (see Conclusion for justification)`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Ships Layer 7 of the `telegram-delivery-robustness` spec on top of the
|
|
11
|
+
already-merged Layer 1 (commit `f9b5e3bb`, PR #100), Layer 2 (commit
|
|
12
|
+
`5b953c17`, PR #101), and Layer 3 (commit `60c64f8e`, PR #103). Layer 7
|
|
13
|
+
is the **templates-drift verifier** — the final piece that closes the
|
|
14
|
+
"no orphan TODO" loop on the original incident's root cause: a deployed
|
|
15
|
+
relay script that drifts away from any known-shipped instar version
|
|
16
|
+
silently, with no operator-visible signal until the next failure
|
|
17
|
+
occurs.
|
|
18
|
+
|
|
19
|
+
The verifier scans deployed instar relay scripts across all agents on
|
|
20
|
+
the host, computes SHA-256 of each on-disk copy, and compares against a
|
|
21
|
+
canonical SHA history. Drifted templates fire a `template-drift-
|
|
22
|
+
detected` `DegradationReporter` event with persistent dedup so a
|
|
23
|
+
long-running drift produces ONE event, not 365. A companion CI lint
|
|
24
|
+
asserts that every historical shipped `telegram-reply.sh` SHA on `main`
|
|
25
|
+
is in the migrator's `TELEGRAM_REPLY_PRIOR_SHIPPED_SHAS` set — closing
|
|
26
|
+
the failure mode where future template upgrades silently strand prior
|
|
27
|
+
deployed agents in the user-modified `.new` candidate path.
|
|
28
|
+
|
|
29
|
+
Files added:
|
|
30
|
+
|
|
31
|
+
- `src/monitoring/templates-drift-verifier.ts` — the verifier core,
|
|
32
|
+
exporting `runVerifier(opts)` (≈260 LoC).
|
|
33
|
+
- `scripts/verify-deployed-templates.ts` — thin CLI wrapper invoked by
|
|
34
|
+
the daily job; reads the kill switch from `.instar/config.json`.
|
|
35
|
+
- `scripts/lint-template-sha-history.ts` — CI lint with a public
|
|
36
|
+
`lintTemplateShaHistory()` export so the unit test can drive it
|
|
37
|
+
without forking a process.
|
|
38
|
+
- `tests/unit/verify-deployed-templates.test.ts` — 7 cases covering
|
|
39
|
+
current/prior/novel SHA fixtures, dedup behavior, kill switch,
|
|
40
|
+
per-agent partial-install, default-discovery, and canonical
|
|
41
|
+
registration.
|
|
42
|
+
- `tests/unit/lint-template-sha-history.test.ts` — 2 cases covering the
|
|
43
|
+
positive lint pass and the regression-on-removal case.
|
|
44
|
+
|
|
45
|
+
Files modified:
|
|
46
|
+
|
|
47
|
+
- `src/core/PostUpdateMigrator.ts` — extends
|
|
48
|
+
`TELEGRAM_REPLY_PRIOR_SHIPPED_SHAS` to include all six historical
|
|
49
|
+
shipped SHAs reachable via `git log --first-parent main` on `src/
|
|
50
|
+
templates/scripts/telegram-reply.sh` (Tier-1 init through Layer 2).
|
|
51
|
+
Visibility flipped from `private static` to `public static readonly`
|
|
52
|
+
so the verifier can reference the same set without duplicating it.
|
|
53
|
+
- `src/commands/init.ts` — registers a new built-in job
|
|
54
|
+
`templates-drift-verifier` (daily at 02:00 local, `haiku` model,
|
|
55
|
+
script-type, low priority). The job's pre-flight gate honors the
|
|
56
|
+
same `config.monitoring.templatesDriftVerifier.enabled` flag the
|
|
57
|
+
verifier itself checks. `refreshJobs()` propagates the new entry
|
|
58
|
+
to existing agents on next `instar update`.
|
|
59
|
+
- `src/data/builtin-manifest.json` — regenerated (entry count 186 → 187).
|
|
60
|
+
|
|
61
|
+
## Decision-point inventory
|
|
62
|
+
|
|
63
|
+
- `runVerifier` (templates-drift-verifier) — **add** — pure read-only
|
|
64
|
+
scan over `.claude/scripts/`, `.instar/scripts/`, and `<root>/scripts/`
|
|
65
|
+
per agent root, compares on-disk SHA against canonical + prior-shipped
|
|
66
|
+
set, emits `template-drift-detected` events deduped via a persistent
|
|
67
|
+
jsonl seen-log.
|
|
68
|
+
- `TELEGRAM_REPLY_PRIOR_SHIPPED_SHAS` (PostUpdateMigrator) — **modify** —
|
|
69
|
+
visibility flipped (private → public static readonly) and the set
|
|
70
|
+
extended to cover six older historical shipped SHAs the prior set was
|
|
71
|
+
missing. No semantic change to migrator behavior; the set was already
|
|
72
|
+
the source of truth, only its membership widened.
|
|
73
|
+
- `getDefaultJobs.templates-drift-verifier` (init.ts) — **add** — daily
|
|
74
|
+
built-in job; new agents get it on first init, existing agents get it
|
|
75
|
+
on next update via `refreshJobs()`.
|
|
76
|
+
- `lintTemplateShaHistory` (CI lint) — **add** — dev-time-only assertion
|
|
77
|
+
that every historical SHA reachable via `git log --first-parent main`
|
|
78
|
+
is in the prior-shipped set OR matches the current bundled template.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 1. Over-block
|
|
83
|
+
|
|
84
|
+
**What legitimate inputs does this change reject that it shouldn't?**
|
|
85
|
+
|
|
86
|
+
The verifier has no block/allow surface — it never modifies on-disk
|
|
87
|
+
content and never refuses any operation. The only "rejection" surface
|
|
88
|
+
is the CI lint, which would block a commit that ships a new template
|
|
89
|
+
SHA without adding the just-superseded SHA to the prior-shipped set.
|
|
90
|
+
This is the correct shape: it forces the developer who's bumping the
|
|
91
|
+
template to update the migration trail in the same PR, which is the
|
|
92
|
+
exact orphan-TODO failure mode this layer exists to prevent.
|
|
93
|
+
|
|
94
|
+
The lint does NOT block on novel commits to unrelated files; it only
|
|
95
|
+
walks `git log -- src/templates/scripts/telegram-reply.sh` and asserts
|
|
96
|
+
SHA coverage on commits that touched that one file.
|
|
97
|
+
|
|
98
|
+
**Conclusion: no over-block.**
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 2. Under-block
|
|
103
|
+
|
|
104
|
+
**What failure modes does this still miss?**
|
|
105
|
+
|
|
106
|
+
- **Other relay templates (slack, whatsapp, imessage).** The verifier
|
|
107
|
+
scans them and emits drift events for any deployed copy that doesn't
|
|
108
|
+
match the bundled source, but they have no prior-shipped SHA tracking
|
|
109
|
+
yet. A user-modified slack-reply.sh that was shipped two versions ago
|
|
110
|
+
would fire a drift event today; that's by design (the operator should
|
|
111
|
+
know), but it's noisier than the telegram-reply.sh path. Mitigation:
|
|
112
|
+
the kill switch silences the entire verifier; per-template kill
|
|
113
|
+
switches were intentionally not added (one switch is the minimum
|
|
114
|
+
surface area).
|
|
115
|
+
- **Templates installed at non-standard paths.** The verifier checks
|
|
116
|
+
three known deployment locations per agent root: `.claude/scripts/`,
|
|
117
|
+
`.instar/scripts/`, and (when the root itself is `.instar/`) the
|
|
118
|
+
immediate `scripts/`. An operator who installed a relay script at,
|
|
119
|
+
e.g., `~/bin/telegram-reply.sh` will not be scanned. This matches
|
|
120
|
+
the deploy paths the migrator writes to, so the only miss is custom
|
|
121
|
+
installs the migrator already doesn't manage.
|
|
122
|
+
- **Project-wide deployments under `~/Documents/Projects/*/.instar/`.**
|
|
123
|
+
Per-project install paths are NOT scanned by default; the verifier
|
|
124
|
+
enumerates `~/.instar/agents/*` only. Per-project agents will get a
|
|
125
|
+
drift event the next time the operator runs `instar update` (the
|
|
126
|
+
migrator runs the same SHA check inline). The trade-off: scanning
|
|
127
|
+
every project under `~/Documents/Projects/` would slow the daily job
|
|
128
|
+
to a crawl on hosts with thousands of unrelated projects, and would
|
|
129
|
+
also cross trust boundaries (those projects may be other users'
|
|
130
|
+
agents; we shouldn't be reading their relay scripts uninvited).
|
|
131
|
+
- **The CI lint can't catch SHA removal in CI.** A future PR that
|
|
132
|
+
deletes a SHA from `TELEGRAM_REPLY_PRIOR_SHIPPED_SHAS` will be caught
|
|
133
|
+
if at least one historical commit's SHA matches the deleted entry —
|
|
134
|
+
which is true today for every entry. If a developer deletes a SHA
|
|
135
|
+
AND also rebases history to remove the commit that produced it, the
|
|
136
|
+
lint won't catch it. This is acceptable because the rebase requires
|
|
137
|
+
force-pushing main, which is itself blocked by a separate gate.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 3. Level-of-abstraction fit
|
|
142
|
+
|
|
143
|
+
**Is this at the right layer?**
|
|
144
|
+
|
|
145
|
+
The verifier is a **detector**, not an authority. It reads the
|
|
146
|
+
filesystem, computes hashes, and emits structured signals into the
|
|
147
|
+
existing `DegradationReporter` channel. It owns no block/allow
|
|
148
|
+
authority; the migrator (`PostUpdateMigrator.migrateReplyScriptToPort
|
|
149
|
+
Config`) is the only piece of code that mutates a deployed relay
|
|
150
|
+
script, and that code path is already gated on SHA membership in the
|
|
151
|
+
prior-shipped set.
|
|
152
|
+
|
|
153
|
+
The split keeps detection (cheap, daily, host-wide) separate from
|
|
154
|
+
mutation (per-`instar update`, per-agent, gated). The CI lint is at
|
|
155
|
+
the right layer too — it asserts an invariant about the prior-shipped
|
|
156
|
+
set's coverage of git history, which is a developer-time concern, not
|
|
157
|
+
a runtime concern.
|
|
158
|
+
|
|
159
|
+
A previous version of this design considered making the verifier
|
|
160
|
+
auto-write a `.new` candidate alongside drifted scripts. That was
|
|
161
|
+
rejected: the migrator already does that on `instar update`, and
|
|
162
|
+
having two code paths that mutate deployed scripts (with different
|
|
163
|
+
trigger frequencies) would race during update. The current design has
|
|
164
|
+
exactly one mutator (the migrator) and one detector (the verifier),
|
|
165
|
+
with no overlap.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 4. Signal vs authority compliance
|
|
170
|
+
|
|
171
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
172
|
+
|
|
173
|
+
**Does this change hold blocking authority with brittle logic?**
|
|
174
|
+
|
|
175
|
+
- [x] **No** — this change produces a signal consumed by an existing
|
|
176
|
+
smart gate. The verifier emits `DegradationReporter.report({...})`
|
|
177
|
+
events, which feed the existing operator-visible degradation channel
|
|
178
|
+
(Telegram alerts via the `degradation-digest` job, dashboard panel,
|
|
179
|
+
health endpoint). The verifier itself never blocks anything; it's a
|
|
180
|
+
detector that lights up a downstream signal lane.
|
|
181
|
+
|
|
182
|
+
The CI lint does hold blocking authority over commits, but its logic
|
|
183
|
+
is **deterministic and finite**: walk N commits, compute hashes,
|
|
184
|
+
compare against a fixed allowed-set. There is no judgment, no
|
|
185
|
+
synonym-matching, no LLM. The signal-vs-authority doc reserves
|
|
186
|
+
"brittle" for string/regex matching on free-form content; SHA-256
|
|
187
|
+
comparison on git-tracked file contents is structurally precise and
|
|
188
|
+
collision-resistant. The lint is the correct shape for this gate.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## 5. Interactions
|
|
193
|
+
|
|
194
|
+
**Does this interact with existing checks, recovery paths, or infrastructure?**
|
|
195
|
+
|
|
196
|
+
- **Shadowing:** the verifier runs daily; the migrator runs on
|
|
197
|
+
`instar update`. They both read the same `TELEGRAM_REPLY_PRIOR_
|
|
198
|
+
SHIPPED_SHAS` set. The verifier never writes; the migrator writes
|
|
199
|
+
only on `instar update`. Order doesn't matter — neither shadows the
|
|
200
|
+
other. If a drift event fires today and the operator runs `instar
|
|
201
|
+
update` tomorrow, the migrator will write a `.new` candidate and emit
|
|
202
|
+
a `relay-script-modified-locally` event (which is a different event
|
|
203
|
+
feature than `template-drift-detected`); the operator gets two
|
|
204
|
+
related signals on the same drift, which is the desired behavior
|
|
205
|
+
(one says "I noticed", one says "I wrote a candidate fix").
|
|
206
|
+
- **Double-fire:** the verifier dedups via the persistent
|
|
207
|
+
`.instar/state/drift-verifier-seen.jsonl` log, keyed on
|
|
208
|
+
`(deployed-path, current-SHA)`. The dedup persists across runs, so
|
|
209
|
+
the daily job emits AT MOST one event per drift. If the operator
|
|
210
|
+
edits the script (creating a new SHA on the same path), the verifier
|
|
211
|
+
emits one fresh event for the new SHA — which is the correct
|
|
212
|
+
behavior because the operator's intent may have changed.
|
|
213
|
+
- **Races:** the seen-log is append-only (`fs.appendFileSync`); the
|
|
214
|
+
verifier runs in a single process. Two concurrent verifiers (e.g.,
|
|
215
|
+
manual run while daily job is firing) would both append a duplicate
|
|
216
|
+
entry; readers tolerate duplicates because the seen-set is built
|
|
217
|
+
from a `Set<string>` of `path::sha` keys. No corruption risk.
|
|
218
|
+
- **Feedback loops:** the verifier emits `template-drift-detected`
|
|
219
|
+
events; the existing `degradation-digest` job reads them and may
|
|
220
|
+
send a Telegram alert. If the alert send itself relied on a drifted
|
|
221
|
+
`telegram-reply.sh`, the alert would fail — and the failure would
|
|
222
|
+
enqueue via the Layer 2 SQLite queue and retry via the Layer 3
|
|
223
|
+
sentinel. So the worst case is: drift detected → alert queued →
|
|
224
|
+
alert recovered after the operator fixes the relay script. No
|
|
225
|
+
infinite loop.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## 6. External surfaces
|
|
230
|
+
|
|
231
|
+
**Does this change anything visible outside the immediate code path?**
|
|
232
|
+
|
|
233
|
+
- **Wire format:** none. No new HTTP endpoints, no new headers, no new
|
|
234
|
+
message shapes.
|
|
235
|
+
- **Telegram users:** the new `template-drift-detected` event flows
|
|
236
|
+
through the existing degradation pipeline; users on hosts with
|
|
237
|
+
drifted scripts will see one Telegram alert per novel drift via
|
|
238
|
+
the `degradation-digest` job. The alert is a fixed-template
|
|
239
|
+
narrative composed by `DegradationReporter.narrativeFor` (no
|
|
240
|
+
template excerpting, no agent text).
|
|
241
|
+
- **Persistent state:** new file at
|
|
242
|
+
`~/.instar/state/drift-verifier-seen.jsonl` (append-only, mode
|
|
243
|
+
0644). Capped implicitly by the finite set of `(path, sha)` pairs
|
|
244
|
+
any host can have; in practice <100 entries even after years of
|
|
245
|
+
agent churn. No retention policy is needed beyond what
|
|
246
|
+
`BackupManager`'s default exclusion already covers (state files
|
|
247
|
+
under `.instar/state/` are not backed up).
|
|
248
|
+
- **Other agents on the same machine:** the verifier reads files
|
|
249
|
+
under `~/.instar/agents/*/` — directories owned by the same
|
|
250
|
+
user account that runs the daily job. No cross-user surface.
|
|
251
|
+
- **CI surface:** the new lint adds ≈3s to a pre-push run via
|
|
252
|
+
`npx tsx scripts/lint-template-sha-history.ts`. It is NOT yet wired
|
|
253
|
+
into `pnpm test:push` — adding it as a test under `tests/unit/`
|
|
254
|
+
was the chosen integration path, which means `pnpm test` covers it.
|
|
255
|
+
Wiring a separate `lint:templates` script can come in a follow-up if
|
|
256
|
+
the test path proves insufficient (it shouldn't).
|
|
257
|
+
- **Default-on flag:** the verifier ships default-on per spec. Operators
|
|
258
|
+
with intentionally customized scripts will see ONE event after
|
|
259
|
+
upgrade and can flip the flag off. This is the spec-mandated
|
|
260
|
+
behavior; we have the rollback path documented in §7.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## 7. Rollback cost
|
|
265
|
+
|
|
266
|
+
**If this turns out wrong in production, what's the back-out?**
|
|
267
|
+
|
|
268
|
+
- **Hot-fix release:** revert the source. The seen-log file becomes
|
|
269
|
+
inert (no readers). Existing daily-job entries in `jobs.json` will
|
|
270
|
+
fail-soft because the verifier script is gone — the gate-then-execute
|
|
271
|
+
shape exits silently when the source isn't found. Operators who
|
|
272
|
+
hand-deleted the daily job entry are unaffected.
|
|
273
|
+
- **Feature flag toggle:** the cleanest rollback is
|
|
274
|
+
`monitoring.templatesDriftVerifier.enabled = false` in the host
|
|
275
|
+
config. No data migration, no user-visible regression. The spec
|
|
276
|
+
documents this as the operator-facing customization path; reverts
|
|
277
|
+
inherit it.
|
|
278
|
+
- **Persistent state:** the seen-log is at
|
|
279
|
+
`~/.instar/state/drift-verifier-seen.jsonl`. A rollback that wipes
|
|
280
|
+
this file leaves the host in a clean state (the next verifier run
|
|
281
|
+
re-emits one event per drift). The file is gitignored (state files
|
|
282
|
+
always are) so there's no cross-machine replay surface.
|
|
283
|
+
- **User visibility during rollback:** an agent with one queued
|
|
284
|
+
`template-drift-detected` event in transit will deliver it before
|
|
285
|
+
the verifier source is gone. A rollback before the next daily run
|
|
286
|
+
produces zero further alerts. The migrator's existing
|
|
287
|
+
`relay-script-modified-locally` event continues to fire on `instar
|
|
288
|
+
update`, so operators retain a signal lane.
|
|
289
|
+
- **CI lint rollback:** delete the test file. The lint becomes an
|
|
290
|
+
orphan script that no longer gates commits. No persistent state.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Conclusion
|
|
295
|
+
|
|
296
|
+
Layer 7 closes the orphan-TODO failure mode that the spec's §7 calls
|
|
297
|
+
out as "the wrong shape for the root cause of this incident." The
|
|
298
|
+
verifier is a read-only detector; the lint is a deterministic
|
|
299
|
+
SHA-history check. Neither holds content authority; both feed
|
|
300
|
+
existing channels (DegradationReporter for the verifier, the
|
|
301
|
+
pre-commit gate for the lint).
|
|
302
|
+
|
|
303
|
+
One small design refinement during implementation: I considered
|
|
304
|
+
having the lint walk the entire git history (`git log` with no `-n`
|
|
305
|
+
limit) and decided against it. A 100-commit window covers every
|
|
306
|
+
historical change to telegram-reply.sh by orders of magnitude (the
|
|
307
|
+
file has 9 historical SHAs total, all within recent history). The
|
|
308
|
+
limit prevents pathological repository walks if the history grows
|
|
309
|
+
large for unrelated reasons.
|
|
310
|
+
|
|
311
|
+
**Second-pass review: not required.** Layer 7 is a meta-infrastructure
|
|
312
|
+
change with no auth surface, no message-content surface, no recovery
|
|
313
|
+
path mutation, and no agent-visible runtime behavior beyond a
|
|
314
|
+
DegradationReporter event. Compared to Layer 3 (which introduced an
|
|
315
|
+
auth-bearing recovery sentinel and earned a second-pass review), this
|
|
316
|
+
layer is structurally simple: 260 LoC of pure detector logic, a 90 LoC
|
|
317
|
+
CLI wrapper, a 130 LoC CI lint. The risk surface is silent failure of
|
|
318
|
+
the verifier (acceptable — the originating incident class is already
|
|
319
|
+
closed by Layers 1-3), not unwanted action. The spec convergence
|
|
320
|
+
process already covered the design at internal + external review
|
|
321
|
+
levels. Ship.
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## Evidence pointers
|
|
326
|
+
|
|
327
|
+
- Unit tests: `tests/unit/verify-deployed-templates.test.ts` (7 cases),
|
|
328
|
+
`tests/unit/lint-template-sha-history.test.ts` (2 cases). All pass.
|
|
329
|
+
- Lint executable proof: `npx tsx scripts/lint-template-sha-history.ts`
|
|
330
|
+
exits 0 with `"OK (scanned 8 commits, current sha256:371d7e8f4f72…)"`.
|
|
331
|
+
- Verifier executable proof: `HOME=/tmp/empty-home npx tsx scripts/
|
|
332
|
+
verify-deployed-templates.ts` exits 0 with
|
|
333
|
+
`{"verifier":"templates-drift","scanned":0,"drifted":0,
|
|
334
|
+
"suppressed":0,"errors":[]}`.
|
|
335
|
+
- Manifest regeneration: `pnpm generate:manifest` increments entry
|
|
336
|
+
count 186 → 187 with the new `job:templates-drift-verifier` entry.
|
|
337
|
+
- Spec: `docs/specs/telegram-delivery-robustness.md` § 7.
|
|
338
|
+
- Predecessor PRs: #100 (Layer 1, `f9b5e3bb`), #101 (Layer 2,
|
|
339
|
+
`5b953c17`), #103 (Layer 3, `60c64f8e`).
|