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