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